題目:node
!思路:其實樹上主席樹是把每一棵主席樹看作樹狀數組上的一個點,每次修改log棵主席樹,求區間和的時候一樣log查詢前綴和。c++
上代碼!git
#include<bits/stdc++.h> #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=2e4+5; int n,m,rt[N],root[N],q[N],cnt,a[N],b[N],tot; struct node{int l,r,num;}t[N*100]; struct data{int x,y,k;}Q[N]; inline int getid(int x){return lower_bound(b+1,b+1+cnt,x)-b;} inline int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;} void update(int l,int r,int &x,int y,int pos,int v){ t[x=++tot]=t[y];t[x].num+=v; if(l==r)return;int mid=(l+r)>>1; if(pos<=mid)update(l,mid,t[x].l,t[y].l,pos,v); else update(mid+1,r,t[x].r,t[y].r,pos,v); } inline void change(int p,int v){ for(int i=p;i<=n;i+=i&-i)update(1,cnt,rt[i],rt[i],a[p],v); } inline int cal(int x){ int sum=0; for(int i=x;i;i-=i&-i)sum+=t[t[q[i]].l].num;return sum; } inline int query(int x,int y,int k){ for(int i=x;i;i-=i&-i)q[i]=rt[i]; for(int i=y;i;i-=i&-i)q[i]=rt[i]; int l=1,r=cnt,qx=x,qy=y;x=root[x];y=root[y]; while(l<r){ int sum=cal(qy)-cal(qx)+t[t[y].l].num-t[t[x].l].num; int mid=(l+r)>>1; if(k<=sum){ for(int i=1;i<=n;i++)q[i]=t[q[i]].l; x=t[x].l;y=t[y].l;r=mid; } else{ for(int i=1;i<=n;i++)q[i]=t[q[i]].r; x=t[x].r;y=t[y].r;l=mid+1;k-=sum; } } return l; } int main() { n=read();m=read();for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];cnt=n; for(int i=1;i<=m;i++){ char ch;cin>>ch; if(ch=='Q')Q[i].x=read(),Q[i].y=read(),Q[i].k=read(); if(ch=='C')Q[i].x=read(),Q[i].k=read(),b[++cnt]=Q[i].k; } sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;for(int i=1;i<=n;i++)a[i]=getid(a[i]); for(int i=1;i<=n;i++)update(1,cnt,root[i],root[i-1],a[i],1); for(int i=1;i<=m;i++){ if(Q[i].y==0){ change(Q[i].x,-1);a[Q[i].x]=getid(Q[i].k);change(Q[i].x,1); } else{ printf("%d\n",b[query(Q[i].x-1,Q[i].y,Q[i].k)]); } } return 0; }
接下來就是調了一天的樹上可修改主席樹!數組
題目:網絡
其實就是樹上主席樹與可修改主席樹的結合,(至於爲何我調了一天,由於我弱阿,義正詞嚴!)。ide
這份代碼仍是要經常溫習啊,懶得打註釋,但願我下次還記得我是怎麼寫的qaqspa
#include<bits/stdc++.h> #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=80005; int n,m,d[N],fa[N][22],head[N],ne[N<<1],to[N<<1],cnt,tot,rt[N],q[N],a[N],b[N<<1],vis[N],dfn[N],tt,num[N],sz[N]; struct node{int l,r,num;}t[N*120];struct data{int k,a,b;}Q[N]; inline int read(){int x,f=1;char ch;_(!)ch=='-'?f=-1:f;x=ch-48;_()x=x*10+ch-48;return f*x;} inline void insert(int u,int v){ne[++tot]=head[u];head[u]=tot;to[tot]=v;} inline int getid(int x){return lower_bound(b+1,b+1+cnt,x)-b;} void update(int l,int r,int &x,int y,int pos,int v){ if(!x)x=++tot;t[x]=t[y];t[x].num+=v; if(l==r)return;int mid=(l+r)>>1; if(pos<=mid)update(l,mid,t[x].l,t[y].l,pos,v); else update(mid+1,r,t[x].r,t[y].r,pos,v); } void dfs(int x){ //update(1,cnt,root[x],root[fa[x][0]],a[x],1); dfn[x]=++tt;num[tt]=x;sz[x]=1; for(int i=head[x];i;i=ne[i]){ if(to[i]==fa[x][0])continue; d[to[i]]=d[x]+1;fa[to[i]][0]=x; dfs(to[i]);sz[x]+=sz[to[i]]; } } inline int Lca(int x,int y){ if(d[x]<d[y])swap(x,y); for(int i=20;i>=0;i--)if(d[fa[x][i]]>=d[y])x=fa[x][i]; if(x==y)return x; for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i]; return fa[x][0]; } inline void change(int p,int x,int v){//if(dfn[p]==0)printf("#%d %d %d ",p,x,sz[x]); for(int i=dfn[p];i<=n;i+=i&-i)update(1,cnt,rt[i],rt[i],a[x],v); } inline void getq(int x){for(int i=dfn[x];i;i-=i&-i)q[i]=rt[i],vis[i]=1;} inline int cal(int x){int sum=0;for(int i=dfn[x];i;i-=i&-i)sum+=t[t[q[i]].l].num,vis[i]=0;return sum;} inline void cagl(int x){for(int i=dfn[x];i;i-=i&-i)if(!vis[i])q[i]=t[q[i]].l,vis[i]=1;} inline void cagr(int x){for(int i=dfn[x];i;i-=i&-i)if(!vis[i])q[i]=t[q[i]].r,vis[i]=1;} inline int query(int x,int y,int a,int b,int k){ getq(x);getq(y);getq(a);getq(b);//printf("#"); int l=1,r=cnt,sum; while(l<r){ int mid=(l+r)>>1; sum=cal(x)+cal(y)-cal(a)-cal(b); if(k<=sum){ cagl(x);cagl(y);cagl(a);cagl(b);r=mid; } else{ cagr(x);cagr(y);cagr(a);cagr(b);l=mid+1;k-=sum; } } return l; } int main() { n=read();m=read();for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i];cnt=n; for(int i=1;i<n;i++){int x,y;x=read();y=read();insert(x,y);insert(y,x);}tot=0; for(int i=1;i<=m;i++){ Q[i].k=read();Q[i].a=read();Q[i].b=read(); if(Q[i].k==0)b[++cnt]=Q[i].b; } sort(b+1,b+1+cnt);cnt=unique(b+1,b+1+cnt)-b-1;for(int i=1;i<=n;i++)a[i]=getid(a[i]);dfn[n+1]=n+1;num[n+1]=n+1; d[1]=1;dfs(1);for(int i=1;i<=20;i++)for(int j=1;j<=n;j++)fa[j][i]=fa[fa[j][i-1]][i-1]; for(int i=1;i<=n;i++){change(i,i,1);change(num[dfn[i]+sz[i]],i,-1);} for(int i=1;i<=m;i++){ if(Q[i].k==0){ change(Q[i].a,Q[i].a,-1);change(num[dfn[Q[i].a]+sz[Q[i].a]],Q[i].a,1); a[Q[i].a]=getid(Q[i].b);change(Q[i].a,Q[i].a,1);change(num[dfn[Q[i].a]+sz[Q[i].a]],Q[i].a,-1); } else { int lca=Lca(Q[i].a,Q[i].b);int k=d[Q[i].a]+d[Q[i].b]-2*d[lca]-Q[i].k+2; if(k<1){puts("invalid request!");continue;} printf("%d\n",b[query(Q[i].a,Q[i].b,lca,fa[lca][0],k)]); } } return 0; }
彷佛還能夠用樹剖套主席樹套樹狀數組...code