[bzoj3123]森林
首先对于询问操作可以使用可持久化线段树来维护,对于连边操作对于两颗树中选取较小的树暴力练到另一个点上,点数可以用并查集然后只修改根的点数即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mid (l+r>>1) 4 #define N 100001 5 struct ji{ 6 int nex,to; 7 }edge[N<<1]; 8 int E,V,n,m,t,x,y,z,ans,a[N],ff[N],sum[N],f[21][N],head[N],sz[20*N],b[N],son[2][20*N],s[N],r[N],vis[N]; 9 char s1[11]; 10 void add(int x,int y){ 11 edge[E].nex=head[x]; 12 edge[E].to=y; 13 head[x]=E++; 14 } 15 int find(int k){ 16 if (k==ff[k])return k; 17 return ff[k]=find(ff[k]); 18 } 19 int ne(int &k){ 20 if (!k)k=++V; 21 return k; 22 } 23 int lca(int x,int y){ 24 if (s[x]<s[y])swap(x,y); 25 for(int i=20;i>=0;i--) 26 if (s[f[i][x]]>=s[y])x=f[i][x]; 27 if (x==y)return x; 28 for(int i=20;i>=0;i--) 29 if (f[i][x]!=f[i][y]){ 30 x=f[i][x]; 31 y=f[i][y]; 32 } 33 return f[0][x]; 34 } 35 void merge(int x,int y){ 36 ff[find(x)]=find(y); 37 sum[find(y)]+=sum[find(x)]; 38 } 39 void update(int k1,int k2,int l,int r,int x){ 40 sz[k1]=sz[k2]+1; 41 if (l==r)return; 42 int p=(x>mid); 43 son[p^1][k1]=son[p^1][k2]; 44 update(ne(son[p][k1]),son[p][k2],l+(mid-l+1)*p,mid+(r-mid)*p,x); 45 } 46 int query(int l,int r,int x,int a,int b,int c,int d){ 47 if (l==r)return l; 48 int t=sz[son[0][a]]+sz[son[0][b]]-sz[son[0][c]]-sz[son[0][d]],p=(x>t); 49 return query(l+(mid-l+1)*p,mid+(r-mid)*p,x-p*t,son[p][a],son[p][b],son[p][c],son[p][d]); 50 } 51 void dfs(int k,int fa){ 52 vis[k]=1; 53 s[k]=s[f[0][k]=fa]+1; 54 for(int i=1;i<=20;i++)f[i][k]=f[i-1][f[i-1][k]]; 55 update(ne(r[k]),r[fa],1,m,a[k]); 56 for(int i=head[k];i!=-1;i=edge[i].nex) 57 if (edge[i].to!=fa)dfs(edge[i].to,k); 58 } 59 int main(){ 60 scanf("%*d%d%d%d",&n,&m,&t); 61 memset(head,-1,sizeof(head)); 62 for(int i=1;i<=n;i++){ 63 scanf("%d",&a[i]); 64 ff[i]=i; 65 sum[i]=1; 66 } 67 for(int i=1;i<=m;i++){ 68 scanf("%d%d",&x,&y); 69 add(x,y); 70 add(y,x); 71 merge(x,y); 72 } 73 memcpy(b,a,sizeof(b)); 74 sort(b+1,b+n+1); 75 m=unique(b+1,b+n+1)-b-1; 76 for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b; 77 for(int i=1;i<=n;i++) 78 if (!vis[i])dfs(i,0); 79 while (t--){ 80 scanf("%s%d%d",s1,&x,&y); 81 x^=ans; 82 y^=ans; 83 if (s1[0]=='Q'){ 84 scanf("%d",&z); 85 printf("%d\n",ans=b[query(1,m,z^ans,r[x],r[y],r[lca(x,y)],r[f[0][lca(x,y)]])]); 86 } 87 if (s1[0]=='L'){ 88 if (sum[find(x)]>sum[find(y)])swap(x,y); 89 add(x,y); 90 add(y,x); 91 merge(x,y); 92 dfs(x,y); 93 } 94 } 95 }