【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]); } } }