[Data]带修改的主席树[树状数组套主席树]
树状数组套主席树
树状数组的每个节点维护的是一段区间,我们将每个区间构造成一棵线段树,这时候如果我们要修改一个值,只需要修改logn个节点即可,
时间复杂度为log^2(n),树状数组维护的区间是数的个数n;离散化时是把所有数(包括要修改的数)全部离散化;
1.修改
在修改之前,我们应先把序列里原来的值在主席树对应节点+1(主席树里维护的是某个数出现的次数),遍历logn棵主席树。在修改时,先把该
数原来的值的在主席树上的对应节点+(-1),再把要修改的值在对应节点+1,并在原数组上修改;
2.查询区间K大
其实查询和普通主席树在原理上并没有什么区别,都是用二分,然后树套树就是把一个区间的主席树拆成了若干部分,(由树状数组来完成),
例:我们要查询区间[l,r]第k大,用一个数组来记录从1到l要经过的每棵主席树的根节点,再用另一个数组来记录从1到r要经过的每棵主席树的
根节点,利用前缀和思想,在查询时先把第一个数组的值的sum累加起来,另一个也一样,两个数组作差,得到的就是区间l到r的数出现的个数,
然后再用二分不断缩小范围,直至l==r;
luogu 2617:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define lowbit(x) x&-x 5 using namespace std; 6 #define maxn 10005 7 int totn=0,cnt=0,a[maxn*2],s[maxn<<1],ls[maxn*600],rs[maxn*600],val[maxn*600],rt[maxn*600],sz=0,ca[maxn*2],cb[maxn*2],totx,toty,n,xx[maxn],yy[maxn],cc[maxn]; 8 //void build(int &p,int l,int r){ 9 // p=++cnt; 10 // if(l!=r){ 11 // int mid=(l+r)/2; 12 // build(ls[p],l,mid); 13 // build(rs[p],mid+1,r); 14 // } 15 //} 16 void insert(int &p,int cmp,int x,int l,int r,int v){ 17 p=++cnt;ls[p]=ls[cmp];rs[p]=rs[cmp];val[p]=val[cmp]+v; 18 if(l!=r){ 19 int mid=(l+r)/2; 20 if(x<=mid){ 21 insert(ls[p],ls[cmp],x,l,mid,v); 22 } 23 else{ 24 insert(rs[p],rs[cmp],x,mid+1,r,v); 25 } 26 } 27 } 28 int query(int l,int r,int k){ 29 int i; 30 if(l==r) return l; 31 int sum=0,mid=l+r>>1; 32 for(int i=1;i<=totx;i++) sum-=val[ls[xx[i]]]; 33 for(int i=1;i<=toty;i++) sum+=val[ls[yy[i]]]; 34 if(k<=sum) { 35 for(i=1;i<=totx;i++) xx[i]=ls[xx[i]]; 36 for(i=1;i<=toty;i++) yy[i]=ls[yy[i]]; 37 return query(l,mid,k);} 38 else { 39 for(int i=1;i<=totx;i++) xx[i]=rs[xx[i]]; 40 for(int i=1;i<=toty;i++) yy[i]=rs[yy[i]]; 41 return query(mid+1,r,k-sum); } 42 } 43 void add(int x,int v){ 44 int k=lower_bound(s+1,s+totn+1,a[x])-s; 45 for(int i=x;i<=n;i+=lowbit(i)) insert(rt[i],rt[i],k,1,totn,v); 46 } 47 int read(){ 48 int s=0; 49 char c; 50 while(c<'0'||c>'9') c=getchar(); 51 while(c>='0'&&c<='9'){ 52 s=s*10+c-48; 53 c=getchar(); 54 } 55 return s; 56 } 57 int main() 58 { 59 int m,l,r,k,i; 60 char ch; 61 n=read();m=read(); 62 for(i=1;i<=n;i++){ 63 a[i]=read(); 64 s[++totn]=a[i]; 65 } 66 for(i=1;i<=m;i++){ 67 scanf(" %c",&ch);//scanf("%d%d",&ca[i],&cb[i]); 68 ca[i]=read();cb[i]=read(); 69 if(ch=='Q') cc[i]=read(); 70 //scanf("%d",&cc[i]); 71 else{ 72 s[++totn]=cb[i]; 73 } 74 } 75 sort(s+1,s+totn+1); 76 sz=unique(s+1,s+totn+1)-s-1; 77 for(i=1;i<=n;i++) 78 add(i,1); 79 // build(rt[0],1,sz); 80 // for(i=1;i<=n;i++){ 81 // insert(rt[i],rt[i-1],lower_bound(s+1,s+sz+1,a[i])-s,1,sz); 82 // } 83 // for(i=1;i<=m;i++){ 84 // scanf("%d%d%d",&l,&r,&k); 85 // printf("%d\n",s[query(rt[l-1],rt[r],1,sz,k)]); 86 // } 87 for(i=1;i<=m;i++){ 88 if(cc[i]){ 89 totx=0; 90 toty=0; 91 for(int j=ca[i]-1;j;j-=lowbit(j)) xx[++totx]=rt[j]; 92 for(int j=cb[i];j;j-=lowbit(j)) yy[++toty]=rt[j]; 93 printf("%d\n",s[query(1,totn,cc[i])]); 94 } 95 else { 96 add(ca[i],-1); 97 a[ca[i]]=cb[i]; 98 add(ca[i],1); 99 } 100 } 101 }