[bzoj3123][洛谷P3302] [SDOI2013]森林(树上主席树+启发式合并)
突然发现好像没有那么难……https://blog.csdn.net/stone41123/article/details/78167288
首先有两个操作,一个查询,一个连接
查询的话,直接在树上建主席树
然后难点在于连接
用启发式合并就可以了(想了半天都没想出来)
每次合并时,我们把小的树接到大的上,然后dfs一遍小的树,更新信息
然后注意数组……别太小也别太大……(被数组大小坑了好几次提交)
1 //minamoto 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 5 char buf[1<<21],*p1=buf,*p2=buf; 6 inline int read(){ 7 #define num ch-'0' 8 char ch;bool flag=0;int res; 9 while(!isdigit(ch=getc())) 10 (ch=='-')&&(flag=true); 11 for(res=num;isdigit(ch=getc());res=res*10+num); 12 (flag)&&(res=-res); 13 #undef num 14 return res; 15 } 16 char obuf[1<<24],*o=obuf; 17 void print(int x){ 18 if(x>9) print(x/10); 19 *o++=x%10+48; 20 } 21 const int N=80005,M=N*200; 22 int ver[N<<2],Next[N<<2],head[N]; 23 int a[N],fa[N],sz[N],b[N]; 24 int n,m,tot,q,size,ans; 25 void add(int u,int v){ 26 ver[++tot]=v,Next[tot]=head[u],head[u]=tot; 27 ver[++tot]=u,Next[tot]=head[v],head[v]=tot; 28 } 29 int L[M],R[M],sum[M],rt[N],cnt; 30 void update(int last,int &now,int l,int r,int x){ 31 sum[now=++cnt]=sum[last]+1; 32 if(l==r) return; 33 int mid=(l+r)>>1; 34 if(x<=mid) R[now]=R[last],update(L[last],L[now],l,mid,x); 35 else L[now]=L[last],update(R[last],R[now],mid+1,r,x); 36 } 37 int query(int u,int v,int lca,int lca_fa,int l,int r,int k){ 38 if(l>=r) return l; 39 int x=sum[L[v]]+sum[L[u]]-sum[L[lca]]-sum[L[lca_fa]]; 40 int mid=(l+r)>>1; 41 if(x>=k) return query(L[u],L[v],L[lca],L[lca_fa],l,mid,k); 42 else return query(R[u],R[v],R[lca],R[lca_fa],mid+1,r,k-x); 43 } 44 inline int hash(int x){ 45 return lower_bound(b+1,b+1+size,x)-b; 46 } 47 int ff(int x){ 48 return fa[x]==x?x:fa[x]=ff(fa[x]); 49 } 50 int st[N][17],d[N],vis[N]; 51 void dfs(int u,int father,int root){ 52 st[u][0]=father; 53 for(int i=1;i<=16;++i) 54 st[u][i]=st[st[u][i-1]][i-1]; 55 ++sz[root]; 56 d[u]=d[father]+1; 57 fa[u]=root; 58 vis[u]=1; 59 update(rt[father],rt[u],1,size,hash(a[u])); 60 for(int i=head[u];i;i=Next[i]){ 61 int v=ver[i]; 62 if(v==father) continue; 63 dfs(v,u,root); 64 } 65 } 66 int LCA(int x,int y){ 67 if(x==y) return x; 68 if(d[x]<d[y]) swap(x,y); 69 for(int i=16;i>=0;--i){ 70 if(d[st[x][i]]>=d[y]) x=st[x][i]; 71 } 72 if(x==y) return x; 73 for(int i=16;i>=0;--i){ 74 if(st[x][i]!=st[y][i]) 75 x=st[x][i],y=st[y][i]; 76 } 77 return st[x][0]; 78 } 79 int main(){ 80 //freopen("testdata.in","r",stdin); 81 int t=read(); 82 n=read(),m=read(),q=read(); 83 for(int i=1;i<=n;++i) 84 a[i]=b[i]=read(),fa[i]=i; 85 sort(b+1,b+1+n); 86 size=unique(b+1,b+1+n)-b-1; 87 for(int i=1;i<=m;++i){ 88 int u=read(),v=read(); 89 add(u,v); 90 } 91 for(int i=1;i<=n;++i) 92 if(!vis[i]) dfs(i,0,i); 93 while(q--){ 94 char ch;int x,y; 95 while(!isupper(ch=getc())); 96 x=read()^ans,y=read()^ans; 97 if(ch=='Q'){ 98 int k=read()^ans; 99 int lca=LCA(x,y); 100 ans=b[query(rt[x],rt[y],rt[lca],rt[st[lca][0]],1,size,k)]; 101 print(ans),*o++='\n'; 102 } 103 else{ 104 add(x,y); 105 int u=ff(x),v=ff(y); 106 if(sz[u]<sz[v]) swap(x,y),swap(u,v); 107 dfs(y,x,u); 108 } 109 } 110 fwrite(obuf,o-obuf,1,stdout); 111 return 0; 112 }
深深地明白自己的弱小