HDU 4417 主席树

权值线段树保存历史版本

然后直接在树上二分

离散化的时候要注意

根据不同情况

要手动二分以及特殊情况的判别

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int R[N],A[N],cnt;
vector<int> V;

struct HisTree{
    int l,r,sum;
}T[N*20];

int getid(int x){
    int l=0,r=V.size()-1;
    while(l<r){
        int mid=(l+r+1)/2;
        if(V[mid]<=x)l=mid;
        else r=mid-1;
    }
    return l+1;
}
void build(int l,int r,int &x,int y,int pos){
    T[++cnt]=T[y],x=cnt,T[x].sum++;
    if(l==r)return;
    int mid=(l+r)/2;
    if(pos<=mid)build(l,mid,T[x].l,T[y].l,pos);
    else build(mid+1,r,T[x].r,T[y].r,pos);
}
int ask(int l,int r,int x,int z){
    if(l==r)return T[x].sum;
    int mid=(l+r)/2;
    if(z<=mid)return ask(l,mid,T[x].l,z);
    else return T[T[x].l].sum+ask(mid+1,r,T[x].r,z);
}
int main(){
    int TT;
    cin>>TT;
    for(int flag=1;flag<=TT;++flag){
        int n,m;
        cin>>n>>m;
        V.clear();
        memset(T,0,sizeof T);
        cnt=0;
        memset(R,0,sizeof R);
        for(int i=1;i<=n;++i)scanf("%d",&A[i]),V.push_back(A[i]);
        sort(V.begin(),V.end());
        V.erase(unique(V.begin(),V.end()),V.end());
        for(int i=1;i<=n;++i)build(1,n,R[i],R[i-1],getid(A[i]));
        printf("Case %d:\n",flag);
        for(int i=1;i<=m;++i){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            if(z<V[0])printf("0\n");
            else printf("%d\n",ask(1,n,R[y+1],getid(z))-ask(1,n,R[x],getid(z)));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/Gipsy_Danger/article/details/83009086
今日推荐