待修改主席树 (树状数组+主席树)

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 二逼平衡树 ——树状数组套主席树

Luogu Dynamic Ranking (带修改的主席树)

Dynamic Ranking(主席树,树套树,树状数组)

[COGS 257]动态排名系统 树状数组套主席树