可持久线段树

思想和可持久化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\n", sorted[pos]);
101         }
102     }
103     
104     
105     return 0;
106 }

猜你喜欢

转载自www.cnblogs.com/lnu161403214/p/9252318.html