思想和可持久化trie一模一样,在历史版本的基础上构建新版本,即只增加发生改变的那条路径。
代码是用可持久化线段树实现的主席树,并通过了poj2104/hdu2665两个求区间第k大题
1 #include<stdio.h> 2 #include<algorithm> 3 #include<string.h> 4 #include<map> 5 #include<queue> 6 #include<set> 7 #include<iostream> 8 #include<vector> 9 #define MAXN 1000005 10 using namespace std; 11 typedef long long ll; 12 13 int tot=1; //注意0节点作为虚拟空节点 14 struct Node{ 15 int sum,lson,rson; 16 Node(){ 17 sum=lson=rson=0; 18 } 19 Node operator + (const Node &t)const 20 { 21 Node res; 22 23 res.sum=sum+t.sum; 24 25 return res; 26 } 27 }node[2000015]; 28 29 30 int ins(int k,int num,int x,int l,int r) //在k树x位置+num并构建新树 31 { int tmp=tot++; 32 int mid=(l+r)/2; 33 if(l==r) 34 { 35 node[tmp].lson=node[tmp].rson=0; 36 node[tmp].sum=node[k].sum+num; 37 } 38 else if(x<=mid) 39 { 40 int t=ins(node[k].lson,num,x,l,mid); 41 int t2=node[k].rson; 42 node[tmp]=node[t]+node[t2]; 43 node[tmp].lson=t,node[tmp].rson=t2; 44 } 45 else 46 { 47 int t2=ins(node[k].rson,num,x,mid+1,r); 48 int t=node[k].lson; 49 node[tmp]=node[t]+node[t2]; 50 node[tmp].lson=t,node[tmp].rson=t2; 51 } 52 53 return tmp; 54 } 55 int query(int lroot,int rroot,int l,int r,int k) //查询第k大 56 { 57 if(l==r) return l; 58 int mid=(l+r)/2; 59 int sum=node[node[rroot].lson].sum-node[node[lroot].lson].sum; 60 61 if(sum>=k) 62 { 63 return query(node[lroot].lson,node[rroot].lson,l,mid,k); 64 } 65 else return query(node[lroot].rson,node[rroot].rson,mid+1,r,k-sum); 66 } 67 int a[100005],sorted[100005],root[100005]; 68 int main() 69 { int T; 70 scanf("%d",&T); 71 while(T--) 72 { 73 tot=1; 74 root[0]=0; 75 int n,m; 76 scanf("%d%d",&n,&m); 77 78 for(int i=1;i<=n;i++) 79 { 80 scanf("%d",&a[i]); 81 sorted[i]=a[i]; 82 } 83 sort( sorted + 1, sorted + 1 + n ); 84 int num = unique( sorted + 1, sorted + n + 1 ) - ( sorted + 1 ); 85 for ( int i = 1; i <= n; ++i ) 86 { 87 88 int pos = lower_bound( sorted + 1, sorted + num + 1, a[i] ) - sorted; 89 90 root[i]=ins(root[i-1],1,pos,1,num); 91 92 93 } 94 int l,r,k; 95 while(m--) 96 { 97 scanf("%d%d%d",&l,&r,&k); 98 99 int pos = query(root[l-1],root[r],1,num,k); 100 printf("%d ", sorted[pos]); 101 } 102 } 103 104 105 return 0; 106 }