题目描述:贴个传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3123
用主席树维护区间k小。对于每个节点,以父亲节点为上一版本。
对于每次加边,进行启发式合并,暴力搜索子树内每几个节点,重构主席树即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define N 80005
#define P 17
using namespace std;
int cyc,n,m,Q,cnt,pre,s[N],Tnum,num[N];
int w[N][P+1],rt[N],flag[N],dep[N];
int k,la[N],ff[N*2],fa[N],size[N];
struct node{int a,b;}map[N*2];
struct point{int lc,rc,size;}t[N*300];
int get(int x){return x^pre;}
void add(int a,int b)
{
map[++k]=(node){a,b};ff[k]=la[a];la[a]=k;
map[++k]=(node){b,a};ff[k]=la[b];la[b]=k;
}
class func_seg_tree
{
public:
void modify(int &x,int pre,int l,int r,int des)
{
t[x=++cnt]=t[pre];t[x].size++;
if(l==r)return;
int mid=l+r>>1;
if(des<=mid)modify(t[x].lc,t[pre].lc,l,mid,des);
else modify(t[x].rc,t[pre].rc,mid+1,r,des);
}
int qry(int a,int b,int c,int d,int l,int r,int k)
{
if(l==r)return num[l];
int A=t[t[a].lc].size,B=t[t[b].lc].size;
int C=t[t[c].lc].size,D=t[t[d].lc].size;
int sum=A+B-C-D,mid=l+r>>1;
if(k<=sum)return qry(t[a].lc,t[b].lc,t[c].lc,t[d].lc,l,mid,k);
return qry(t[a].rc,t[b].rc,t[c].rc,t[d].rc,mid+1,r,k-sum);
}
}T;
void dfs(int x)
{
flag[x]=1;size[x]=1;
T.modify(rt[x],rt[w[x][0]],1,Tnum,s[x]);
for(int i=1;i<=P;i++)
w[x][i]=w[w[x][i-1]][i-1];
for(int a=la[x];a;a=ff[a])
if(!flag[map[a].b])
{
w[map[a].b][0]=x;dep[map[a].b]=dep[x]+1;
dfs(map[a].b);size[x]+=size[map[a].b];
}
flag[x]=0;
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=P;i>=0;i--)
if(dep[w[x][i]]>=dep[y])x=w[x][i];
if(x==y)return x;
for(int i=P;i>=0;i--)
if(w[x][i]!=w[y][i])x=w[x][i],y=w[y][i];
return w[x][0];
}
int find(int x)
{
if(!fa[x])return x;
return fa[x]=find(fa[x]);
}
int main()
{
int a,b,x,y,z,pos,X,Y;char ch;
scanf("%d%d%d%d",&cyc,&n,&m,&Q);
for(int i=1;i<=n;i++)
scanf("%d",&s[i]),num[i]=s[i];
sort(num+1,num+n+1);
Tnum=unique(num+1,num+n+1)-num-1;
for(int i=1;i<=n;i++)
s[i]=lower_bound(num+1,num+Tnum+1,s[i])-num;
for(int i=1;i<=m;i++)
scanf("%d%d",&a,&b),add(a,b);
for(int i=1;i<=n;i++)if(!w[i][0])dep[i]=1,dfs(i);
while(Q--)
{
scanf(" %c%d%d",&ch,&x,&y);
x=get(x);y=get(y);
if(ch=='Q')
{
scanf("%d",&z);z=get(z);pos=lca(x,y);
printf("%d\n",pre=T.qry(rt[x],rt[y],rt[pos],rt[w[pos][0]],1,Tnum,z));
}
else
{
int X=find(x),Y=find(y);
if(size[X]>size[Y])swap(x,y);
w[x][0]=y;dep[x]=dep[y]+1;
dfs(x);add(x,y);
}
}
return 0;
}