【bzoj1901】dynamic ranking(带修改主席树)

传送门(权限)

传送门(非权限)

花了一晚上总算把代码调好了……才知道待修改主席树怎么操作……

然而还是一知半解orz……

先说说我的理解吧

我们一般建主席树的时候都是直接在序列上建的

但是如果有修改操作怎么办?

因为主席树维护的是前缀和

而树状数组刚好支持待修改前缀和

所以我们可以将主席树和树状数组一起使用

树状数组实际指向主席树上的节点

修改和查询操作用树状数组遍历,实则修改或查询主席树上的节点

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 #define N 10005
 4 using namespace std;
 5 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
 6 char buf[1<<21],*p1=buf,*p2=buf;
 7 inline int read(){
 8     #define num ch-'0'
 9     char ch;bool flag=0;int res;
10     while(!isdigit(ch=getc()))
11     (ch=='-')&&(flag=true);
12     for(res=num;isdigit(ch=getc());res=res*10+num);
13     (flag)&&(res=-res);
14     #undef num
15     return res;
16 }
17 char obuf[1<<24],*o=obuf;
18 void print(int x){
19     if(x>9) print(x/10);
20     *o++=x%10+48;
21 }
22 inline int lowbit(int x){return x&(-x);}
23 int sum[N*600],L[N*600],R[N*600];
24 int xx[N],yy[N],rt[N],a[N],b[N<<1],ca[N],cb[N],cc[N];
25 int n,q,m,cnt=0,totx,toty;
26 void update(int last,int &now,int l,int r,int x,int v){
27     sum[now=++cnt]=sum[last]+v;
28     L[now]=L[last],R[now]=R[last];
29     if(l==r) return;
30     int mid=(l+r)>>1;
31     if(x<=mid) update(L[last],L[now],l,mid,x,v);
32     else update(R[last],R[now],mid+1,r,x,v);
33 }
34 int query(int l,int r,int q){
35     if(l==r) return l;
36     int x=0,mid=(l+r)>>1;
37     for(int i=1;i<=totx;++i) x-=sum[L[xx[i]]];
38     for(int i=1;i<=toty;++i) x+=sum[L[yy[i]]];
39     if(q<=x){
40         for(int i=1;i<=totx;++i) xx[i]=L[xx[i]];
41         for(int i=1;i<=toty;++i) yy[i]=L[yy[i]];
42         return query(l,mid,q);
43     }
44     else{
45         for(int i=1;i<=totx;++i) xx[i]=R[xx[i]];
46         for(int i=1;i<=toty;++i) yy[i]=R[yy[i]];
47         return query(mid+1,r,q-x);
48     }
49 }
50 void add(int x,int y){
51     int k=lower_bound(b+1,b+1+m,a[x])-b;
52     for(int i=x;i<=n;i+=lowbit(i)) update(rt[i],rt[i],1,m,k,y);
53 }
54 int main(){
55     //freopen("testdata.in","r",stdin);
56     n=read(),q=read();
57     for(int i=1;i<=n;++i)
58     b[++m]=a[i]=read();
59     for(int i=1;i<=q;++i){
60         char ch;
61         while(!isupper(ch=getc()));
62         ca[i]=read(),cb[i]=read();
63         if(ch=='Q') cc[i]=read();else b[++m]=cb[i];
64     }
65     sort(b+1,b+1+m);
66     m=unique(b+1,b+1+m)-b-1;
67     for(int i=1;i<=n;++i) add(i,1);
68     for(int i=1;i<=q;++i){
69         if(cc[i]){
70             totx=toty=0;
71             for(int j=ca[i]-1;j;j-=lowbit(j)) xx[++totx]=rt[j];
72             for(int j=cb[i];j;j-=lowbit(j)) yy[++toty]=rt[j];
73             print(b[query(1,m,cc[i])]),*o++='\n';
74         }
75         else{add(ca[i],-1),a[ca[i]]=cb[i],add(ca[i],1);}
76     }
77     fwrite(obuf,o-obuf,1,stdout);
78     return 0;
79 }

然而我太菜了不会树套树和整体二分……

这里是zcysky大佬的树套树

这里是will大爷的整体二分

posted @ 2018-07-31 08:36  bztMinamoto  阅读(315)  评论(0编辑  收藏  举报
Live2D