hdu 4417 Super Mario

主席树求区间小于某个数的数的个数模板(静态)

#include <bits/stdc++.h>
using namespace std;
const int M = 1e5+7;
int _,n,q,a[M],ls[M],tot,sz,pos,cas=1;
int L[20*M],R[20*M],T[20*M],num[20*M];
void build(int l,int r,int &rt){
    rt=++tot;
    num[rt]=0;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(l,mid,L[rt]);
    build(mid+1,r,R[rt]);
}
void update(int l,int r,int &rt,int pre){
    rt=++tot;
    num[rt]=(num[pre]+1);
    if(l==r) return ;
    L[rt]=L[pre];R[rt]=R[pre];
    int mid=(l+r)>>1;
    if(pos<=mid) update(l,mid,L[rt],L[pre]);
    else update(mid+1,r,R[rt],R[pre]);
}
int query(int ll,int rr,int l,int r,int lrt,int rrt){
    if(ll<=l&&r<=rr){
        return num[rrt]-num[lrt];
    }
    int mid=(l+r)>>1,res=0;
    if(ll<=mid) res+=query(ll,rr,l,mid,L[lrt],L[rrt]);
    if(rr>mid) res+=query(ll,rr,mid+1,r,R[lrt],R[rrt]);
    return res;
}
void solve(){
    printf("Case %d:\n",cas++);tot=0;
    build(1,sz,T[0]);
    for(int i=1;i<=n;i++){
        pos=lower_bound(ls+1,ls+sz+1,a[i])-ls;
        update(1,sz,T[i],T[i-1]);
    }
    while(q--){
        int l,r,h,x;
        scanf("%d%d%d",&l,&r,&h);
        x=upper_bound(ls+1,ls+sz+1,h)-ls-1;
        //cout<<"x:"<<x<<endl;
        if(x==0){
            printf("0\n");continue;
        }
        printf("%d\n",query(1,x,1,sz,T[l],T[r+1]));
    }
}
int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    scanf("%d",&_);
    while(_--){
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),ls[i]=a[i];
        sort(ls+1,ls+n+1);
        sz=unique(ls+1,ls+n+1)-ls-1;
        solve();
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/LMissher/p/9565287.html