[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 }
View Code

 

posted @ 2019-07-28 10:38  PYWBKTDA  阅读(159)  评论(0编辑  收藏  举报