首页 > 代码库 > [POJ2104/HDU2665]Kth Number-主席树-可持久化线段树

[POJ2104/HDU2665]Kth Number-主席树-可持久化线段树

Problem Kth Number

Solution

裸的主席树,模板题。但是求k大的时候需要非常注意,很多容易写错的地方。卡了好久。写到最后还给我来个卡空间。 
具体做法参见主席树论文《可持久化数据结构研究》。

AC Code

#include "cstdio"
#include "iostream"
#include "cstring"
#include "algorithm"
using namespace std;
int T,a[100010],root[100010],b[100010],l,r,k,tot;
struct discre{
    int num,sum;
}dctz[100010];
struct tree{
    int lc,rc,sum;
}tr[100010*21];
bool cmp(discre a,discre b){
    return a.sum<b.sum;
}
void build(int now,int l,int r){
    int mid=(l+r)/2;
    tr[now].sum=0;
    if(l==r){
        return;
    }
    tr[now].lc=++tot;
    build(tot,l,mid);
    tr[now].rc=++tot;
    build(tot,mid+1,r);
}
void insert(int last,int sum,int l,int r){
    tr[++tot]=tr[last];
    tr[tot].sum++;
    int x=tot;
    if(l==r){
        return;
    }
    int mid=(l+r)/2;
    if(sum>mid){
        tr[tot].rc=tot+1;
        insert(tr[last].rc,sum,mid+1,r);
    }else{
        tr[tot].lc=tot+1;
        insert(tr[last].lc,sum,l,mid);
    }
}
int search(int k,int l,int r,int lx,int rx){
    if(lx==rx){
        return lx;
    }
    int mid=(lx+rx)/2;
    int x=tr[tr[r].lc].sum-tr[tr[l].lc].sum;
    if((x>=k))return search(k,tr[l].lc,tr[r].lc,lx,mid);
    else return search(k-x,tr[l].rc,tr[r].rc,mid+1,rx);
}
int main(){
    freopen("chairmantree.in","r",stdin);
    scanf("%d",&T);
    while(T--){
        memset(tr,sizeof(tr),0);
        memset(a,sizeof(a),0);
        memset(dctz,sizeof(dctz),0);
        memset(root,sizeof(root),0);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            dctz[i].sum=a[i];
            dctz[i].num=i;
        }
        sort(dctz+1,dctz+n+1,cmp);
        for(int i=1;i<=n;i++)a[dctz[i].num]=i,b[i]=dctz[i].sum;
        tot=1;
        root[0]=1;
        tr[1].sum=1;
        build(1,1,n);
        for(int i=1;i<=n;i++){
            root[i]=tot+1;
            insert(root[i-1],a[i],1,n);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&l,&r,&k);
            int x=search(k,root[l-1],root[r],1,n);
            printf("%d\n",b[x]);
        }
    }
}

 

[POJ2104/HDU2665]Kth Number-主席树-可持久化线段树