1. 程式人生 > >待修改主席樹 (樹狀數組+主席樹)

待修改主席樹 (樹狀數組+主席樹)

scanf pos spa end tor cal pan name gin

終於學了這個我仰慕已久的算法。

對於待修改的主席樹我們只需要多開一維,進行修改後的求和。復雜度進化為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 }

待修改主席樹 (樹狀數組+主席樹)