主席树+启发式合并
更新lca倍增表时,原本是dfs(x,0),所以更新父亲时放在for循环里不会出现问题,但是在进行合并操作后,更新倍增表就会出现问题
#include<bits/stdc++.h>
using namespace std;
const int maxn = 8e4 + 5;
int a[maxn], prt[maxn], T[maxn], sum[maxn];
int vis[maxn], dep[maxn], fa[maxn][21];
int ver[maxn*4], Next[maxn*4], head[maxn];
int tot, times;
char s[5];
struct node{ int l, r, sum; } tree[maxn*200];
int getpa(int x){ return x == prt[x] ? x : prt[x] = getpa(prt[x]); }
void Add(int x,int y)
{
ver[++tot] = y; Next[tot] = head[x]; head[x] = tot;
}
void init()
{
T[0] = times = 0;
tree[0].l = tree[0].r = tree[0].sum = 0;
}
void update(int &rt,int num,int l,int r)
{
tree[++times] = tree[rt]; rt = times;
tree[rt].sum++;
if(l == r) return ;
int mid = (l+r)>>1;
if(mid >= num) update(tree[rt].l,num,l,mid);
else update(tree[rt].r,num,mid+1,r);
}
int query(int t1,int t2,int t3,int t4,int num,int l,int r)
{
if(l == r) return l;
int tmp = tree[tree[t1].l].sum+tree[tree[t2].l].sum-tree[tree[t3].l].sum-tree[tree[t4].l].sum;
int mid = (l+r)>>1;
if(tmp >= num) return query(tree[t1].l,tree[t2].l,tree[t3].l,tree[t4].l,num,l,mid);
return query(tree[t1].r,tree[t2].r,tree[t3].r,tree[t4].r,num-tmp,mid+1,r);
}
void dfs(int u,int f)
{
vis[u] = 1; T[u] = T[f];
dep[u] = dep[f]+1; fa[u][0] = f;
update(T[u],a[u],0,1e9);
for(int i = 0; i <= 19; i++) fa[u][i+1] = fa[fa[u][i]][i];
for(int i = head[u]; i; i = Next[i]){
int v = ver[i];
if(v == f) continue;
//fa[v][0] = u;
dfs(v,u);
}
}
int lca(int x,int y)
{
if(dep[x] < dep[y]) swap(x,y);
for(int i = 20; i >= 0; i--){
if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
}
for(int i = 20; i >= 0; i--){
if(fa[x][i] != fa[y][i]){
x = fa[x][i]; y = fa[y][i];
}
}
return fa[x][0];
}
int main()
{
int mycase, n, m, q, x, y, z, lastans = 0;
scanf("%d",&mycase);
scanf("%d%d%d",&n,&m,&q);
for(int i = 1; i <= n; i++){
scanf("%d",&a[i]);
prt[i] = i; sum[i] = 1;
}
for(int i = 1; i <= m; i++){
scanf("%d%d",&x,&y);
Add(x,y); Add(y,x);
sum[getpa(y)] += sum[getpa(x)];
prt[getpa(x)] = getpa(y);
}
init();
for(int i = 1; i <= n; i++){
if(!vis[i]) dfs(i,0);
}
while(q--){
scanf("%s%d%d",s,&x,&y);
if(s[0] == 'Q'){
scanf("%d",&z);
x ^= lastans; y ^= lastans; z ^= lastans;
int tmp = lca(x,y);
lastans = query(T[x],T[y],T[tmp],T[fa[tmp][0]],z,0,1e9);
printf("%d\n",lastans);
}
else{
x ^= lastans; y ^= lastans;
Add(x,y); Add(y,x);
if(sum[getpa(x)] < sum[getpa(y)]) swap(x,y);
sum[getpa(x)] += sum[getpa(y)];
prt[getpa(y)] = getpa(x);
dfs(y,x);
}
}
return 0;
}