先考虑对于一棵树进行路径查询,当然可以树链剖分,但没必要。
对于一个询问 [ x , y ] ,可以转化为 [ x , root ] + [ y , root ] - 2 [ lca , root ] + lca,即 [ x , root ] + [ y , root ] - [ lca , root ] - [ fa [ lca ] , root ]
所以只要统计节点到根节点的信息就可以了,求第k小,显然要用主席树。
我们知道,主席树的基本思想是前缀和,在序列上时,以前一个为pre;在树上时,只要以这个节点的父亲为pre就可以了。
这样就解决了询问。
对于连边,可以启发式合并。简而言之就是小树往大树上连。
启发式合并中,每个节点只有在当前size较小时才会被合并,每次合并后体积至少扩大为原来的两倍。所以总复杂度是O(NlogN)。因为更新倍增数组和插入是O(logN)的,所以带了两个log,还是可以接受的。
最后注意要离散化,数组要开大。
1 #include<cstdio>
2 #include<algorithm>
3 #include<string>
4 #include<cstring>
5 #include<cstdlib>
6 using namespace std;
7
8 int read(){
9 int x=0;char ch=getchar();
10 while(ch<'0'||ch>'9')ch=getchar();
11 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
12 return x;
13 }
14
15 const int N=80005;
16
17 int testcase,n,m,t,ans=0;
18 char op[3];
19 int x,y,k;
20
21 struct node{
22 int y,nxt;
23 }e[N*4];
24 int h[N],tot=0;
25 void ad(int x,int y){
26 ++tot;e[tot].y=y;e[tot].nxt=h[x];h[x]=tot;
27 }
28
29 int fa[N];
30 int find(int x){
31 return x==fa[x]?x:fa[x]=find(fa[x]);
32 }
33
34 int root[N],cnt=0;;
35 int val[N],b[N],len;
36 struct Tree{
37 int ls,rs,sz;
38 }tr[N*600];
39 int build(int l,int r){
40 int rt=++cnt;
41 tr[rt].sz=0;
42 if(l==r)return rt;
43 int mid=(l+r)>>1;
44 tr[rt].ls=build(l,mid);
45 tr[rt].rs=build(mid+1,r);
46 return rt;
47 }
48 int sz[N],st[N][18],dep[N],vis[N];
49 int Hash(int x){
50 return lower_bound(b+1,b+len+1,x)-b;
51 }
52 void insert(int &now,int pre,int l,int r,int x){
53 now=++cnt;
54 tr[now]=tr[pre];++tr[now].sz;
55 if(l==r)return;
56 int mid=(l+r)>>1;
57 if(x<=mid)insert(tr[now].ls,tr[pre].ls,l,mid,x);
58 else insert(tr[now].rs,tr[pre].rs,mid+1,r,x);
59 }
60 void dfs(int x,int father,int rt){
61 dep[x]=dep[father]+1;
62 st[x][0]=father;++sz[rt];
63 vis[x]=1;fa[x]=father;
64 for(int j=1;j<=17;++j)st[x][j]=st[st[x][j-1]][j-1];
65 insert(root[x],root[father],1,len,Hash(val[x]));
66 for(int i=h[x];i;i=e[i].nxt){
67 int y=e[i].y;
68 if(y==father)continue;
69 dfs(y,x,rt);
70 }
71 }
72 int LCA(int x,int y){
73 if(dep[x]<dep[y])swap(x,y);
74 for(int j=17;j>=0;--j)if(dep[st[x][j]]>=dep[y])x=st[x][j];
75 if(x==y)return x;
76 for(int j=17;j>=0;--j){
77 if(st[x][j]!=st[y][j])x=st[x][j],y=st[y][j];
78 }
79 return st[x][0];
80 }
81 int ask(int x,int y,int lca,int flca,int l,int r,int k){
82 if(l==r)return b[l];
83 int lsz=tr[tr[x].ls].sz+tr[tr[y].ls].sz-tr[tr[lca].ls].sz-tr[tr[flca].ls].sz;
84 int mid=(l+r)>>1;
85 if(k<=lsz)return ask(tr[x].ls,tr[y].ls,tr[lca].ls,tr[flca].ls,l,mid,k);
86 return ask(tr[x].rs,tr[y].rs,tr[lca].rs,tr[flca].rs,mid+1,r,k-lsz);
87 }
88
89 int main(){
90 testcase=read();n=read();m=read();t=read();
91 for(int i=1;i<=n;++i){
92 val[i]=read();b[i]=val[i];fa[i]=i;
93 }
94 sort(b+1,b+n+1);
95 len=unique(b+1,b+n+1)-b-1;
96 while(m--){
97 x=read();y=read();
98 ad(x,y);ad(y,x);
99 }
100 root[0]=build(1,len);
101 for(int i=1;i<=n;++i){
102 if(!vis[i])dfs(i,0,i),fa[i]=i;
103 }
104 while(t--){
105 scanf("%s",op);
106 x=read();y=read();
107 x^=ans,y^=ans;
108 if(op[0]=='L'){
109 ad(x,y);ad(y,x);
110 int fx=find(x),fy=find(y);
111 if(sz[fx]>sz[fy]){
112 swap(x,y);swap(fx,fy);
113 }
114 dfs(x,y,fy);
115 }
116 else {
117 k=read();k^=ans;
118 int lca=LCA(x,y);
119 ans=ask(root[x],root[y],root[lca],root[st[lca][0]],1,len,k);
120 printf("%d\n",ans);
121 }
122 }
123 }