待修改主席树 (树状数组+主席树)
Posted 大奕哥&VANE
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了待修改主席树 (树状数组+主席树)相关的知识,希望对你有一定的参考价值。
终于学了这个我仰慕已久的算法。
对于待修改的主席树我们只需要多开一维,进行修改后的求和。复杂度进化为O(nlog^2n)
我们需要开R0 L0两个数组记录树状数组的“路径”
然后其他操作就和主席树一样咯!
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=60006; 4 vector<int>v; 5 int n,m,cnt,mx; 6 int R0[N],L0[N],a[N],R[N],rt[N]; 7 struct node 8 { 9 int l,r,s; 10 }t[N*40]; 11 struct que 12 { 13 int f,l,r,x,p,k; 14 }q[N/6]; 15 inline int get(int x){return lower_bound(v.begin(),v.end(),x)-v.begin()+1;} 16 void build(int &x,int l,int r) 17 { 18 int m=(l+r)>>1;x=++cnt; 19 if(l<r) 20 build(t[x].l,l,m),build(t[x].r,m+1,r); 21 } 22 inline int lowbit(int x){return x&(-x);} 23 int update(int l,int r,int p,int root,int w) 24 { 25 int x=++cnt;int m=(l+r)>>1; 26 t[x].s=t[root].s+w; 27 if(l==r)return x; 28 if(p<=m) 29 { 30 t[x].l=update(l,m,p,t[root].l,w); 31 t[x].r=t[root].r; 32 } 33 else 34 { 35 t[x].r=update(m+1,r,p,t[root].r,w); 36 t[x].l=t[root].l; 37 } 38 return x; 39 } 40 void add(int pos,int x,int w) 41 { 42 for(;pos<=n;pos+=lowbit(pos))R[pos]=update(1,mx,x,R[pos],w); 43 } 44 int query(int l,int r,int k,int lrt,int rrt) 45 { 46 if(l==r)return l; 47 int ls=0,rs=0,m=(l+r)>>1; 48 int sum=t[t[rrt].l].s-t[t[lrt].l].s; 49 for(int i=1;i<=R0[0];++i)rs+=t[t[R0[i]].l].s; 50 for(int i=1;i<=L0[0];++i)ls+=t[t[L0[i]].l].s; 51 if(k<=rs-ls+sum) 52 { 53 for(int i=1;i<=R0[0];++i)R0[i]=t[R0[i]].l; 54 for(int i=1;i<=L0[0];++i)L0[i]=t[L0[i]].l; 55 return query(l,m,k,t[lrt].l,t[rrt].l); 56 } 57 else 58 { 59 for(int i=1;i<=R0[0];++i)R0[i]=t[R0[i]].r; 60 for(int i=1;i<=L0[0];++i)L0[i]=t[L0[i]].r; 61 return query(m+1,r,k-rs+ls-sum,t[lrt].r,t[rrt].r); 62 } 63 } 64 void cal(int l,int r,int k) 65 { 66 R0[0]=L0[0]=0; 67 for(int x=r;x;x-=lowbit(x)) 68 { 69 R0[++R0[0]]=R[x]; 70 } 71 for(int x=l;x;x-=lowbit(x)) 72 { 73 L0[++L0[0]]=R[x]; 74 } 75 printf("%d\n",v[query(1,mx,k,rt[l],rt[r])-1]); 76 } 77 char s[3]; 78 int main() 79 { 80 scanf("%d%d",&n,&m); 81 for(int i=1;i<=n;++i) 82 { 83 scanf("%d",&a[i]);v.push_back(a[i]); 84 }mx=n+m; 85 for(int i=1;i<=m;++i) 86 { 87 scanf("%s",s); 88 if(s[0]==‘Q‘) 89 { 90 scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);q[i].f=0; 91 } 92 else 93 { 94 scanf("%d%d",&q[i].p,&q[i].x);q[i].f=1;v.push_back(q[i].x); 95 } 96 } 97 sort(v.begin(),v.end()); 98 v.erase(unique(v.begin(),v.end()),v.end());mx=v.size(); 99 build(rt[0],1,mx); 100 for(int i=1;i<=n;++i)rt[i]=update(1,mx,get(a[i]),rt[i-1],1); 101 for(int i=1;i<=m;++i) 102 { 103 if(!q[i].f)cal(q[i].l-1,q[i].r,q[i].k); 104 else 105 { 106 add(q[i].p,get(a[q[i].p]),-1);add(q[i].p,get(q[i].x),1); 107 a[q[i].p]=q[i].x; 108 } 109 } 110 return 0; 111 }
以上是关于待修改主席树 (树状数组+主席树)的主要内容,如果未能解决你的问题,请参考以下文章
P2617 Dynamic Rankings(主席树+树状数组)
BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树