「BZOJ3123」[SDOI2013]森林
用主席树记录每个节点到根节点的信息,用树上差分的思想查询。
合并时把节点数小的合并到节点数大的上,也就是启发式合并,
合并时重建小树上的主席树。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 const int N=80010,M=N*128,P=20; 6 int n,m,q,maxp,a[N],rank[N],pos[N]; 7 int fa[N][P],dep[N],siz[N]; 8 int root[N],treeroot[N]; 9 int tot,lc[M],rc[M],sum[M]; 10 vector<int>g[N]; 11 int cmp(const int x,const int y){return a[x]<a[y];} 12 inline int read(){ 13 int x=0,w=1;char c=0; 14 while(c<'0'||c>'9'){if(c=='-') w=-1;c=getchar();} 15 while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar(); 16 return x*w; 17 } 18 void insert(int& k,int l,int r,int v){ 19 tot++; 20 lc[tot]=lc[k],rc[tot]=rc[k],sum[tot]=sum[k]+1; 21 k=tot; 22 if(l==r) return; 23 int mid=(l+r)>>1; 24 if(v<=mid) insert(lc[k],l,mid,v); 25 else insert(rc[k],mid+1,r,v); 26 return; 27 } 28 int que(int now1,int now2,int pre1,int pre2,int l,int r,int k){ 29 if(l==r) return l; 30 int mid=(l+r)>>1; 31 int lsum=sum[lc[now1]]+sum[lc[now2]]-sum[lc[pre1]]-sum[lc[pre2]]; 32 if(lsum>=k) return que(lc[now1],lc[now2],lc[pre1],lc[pre2],l,mid,k); 33 else return que(rc[now1],rc[now2],rc[pre1],rc[pre2],mid+1,r,k-lsum); 34 } 35 void dfs(int k,int father,int d,int r){ //dfs同时建立主席树 36 treeroot[k]=r,fa[k][0]=father,dep[k]=d,siz[k]=1; 37 int x; 38 for(int i=1;i<=17;i++) fa[k][i]=fa[fa[k][i-1]][i-1]; 39 for(int i=0;i<g[k].size();i++){ 40 x=g[k][i]; 41 if(x==father) continue; 42 root[x]=root[k]; 43 insert(root[x],1,n,rank[x]); 44 dfs(x,k,d+1,r); 45 siz[k]+=siz[x]; 46 } 47 return; 48 } 49 int getlca(int x,int y){ 50 if(dep[x]<dep[y]) swap(x,y); 51 for(int i=17;i>=0;i--) 52 if(dep[fa[x][i]]>=dep[y]) x=fa[x][i]; 53 if(x==y) return x; 54 for(int i=17;i>=0;i--) 55 if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; 56 return fa[x][0]; 57 } 58 void marge(int s,int t){ 59 if(siz[treeroot[s]]<siz[treeroot[t]]) swap(s,t); 60 root[t]=root[s]; 61 insert(root[t],1,n,rank[t]); 62 dfs(t,s,dep[s]+1,treeroot[s]); 63 return; 64 } 65 void reset(){ 66 tot=0; 67 for(int i=1;i<=n;i++) g[i].clear(); 68 return; 69 } 70 void solve(){ 71 char opt[10]; 72 int t1,t2,t3; 73 n=read(),m=read(),q=read(); 74 for(int i=1;i<=n;i++) a[i]=read(),pos[i]=i; 75 sort(pos+1,pos+n+1,cmp); 76 for(int i=1;i<=n;i++) rank[pos[i]]=i; 77 for(int i=1;i<=m;i++){t1=read(),t2=read();g[t1].push_back(t2);g[t2].push_back(t1);} 78 for(int i=1;i<=n;i++) if(!dep[i]){ 79 root[i]=0; 80 insert(root[i],1,n,rank[i]); 81 dfs(i,0,1,i); 82 } 83 int lastans=0; 84 while(q--){ 85 scanf("%s",opt); 86 t1=read(),t2=read(); 87 if(opt[0]=='Q'){ 88 t3=read(); 89 t1^=lastans,t2^=lastans,t3^=lastans; 90 int lca=getlca(t1,t2); 91 lastans=a[pos[que(root[t1],root[t2],root[lca],root[fa[lca][0]],1,n,t3)]]; 92 printf("%d\n",lastans); 93 }else{ 94 t1^=lastans,t2^=lastans; 95 g[t1].push_back(t2);g[t2].push_back(t1); 96 marge(t1,t2); 97 } 98 } 99 reset(); 100 return; 101 } 102 int main(){ 103 int T; 104 while(scanf("%d",&T)!=EOF) solve(); 105 return 0; 106 }