这道题是主席树维护树上K大值。需要可持久化线段树启发式合并。
没有link的话就和count on a tree 一样,有link的话就暴力重构size较小的树,时间复杂度....
真的是头铁。。。
树剖求lca维护起来好麻烦啊。。。可能是我的锅
UPD:就是我的锅....启发式合并一直写的是错的...
倍增的话维护lca就很简单了
坑点:T表示的是数据是第几组。。。
树剖写的在bzoj上T了 划掉!是我的启发式合并写的和个智障一样!!!!BZOJ上也A了!
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=80005;
int T,n,m,q,fa[N],blo,p[N],dep[N],SIZ[N],son[N],top[N],head[N],ecnt,to[N<<1],nxt[N<<1],root[N],cnt,tot,rt[N],ls[80000*500],rs[80000*500],siz[80000*500],LSH,lsh[N],bl[N];
inline int rd(){
int x=0;char ch=' ';int f=1;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
void add(int bg,int ed) {
nxt[++ecnt]=head[bg];
to[ecnt]=ed;
head[bg]=ecnt;
}
void update(int &k,int pre,int l,int r,int val) {
k=++tot;
ls[k]=ls[pre],rs[k]=rs[pre],siz[k]=siz[pre]+1;
if(l<r) {
int mid=l+r>>1;
if(val<=mid) update(ls[k],ls[pre],l,mid,val);
else update(rs[k],rs[pre],mid+1,r,val);
}
}
void build(int &k,int l,int r) {
k=++tot;
if(l<r) {
int mid=l+r>>1;
build(ls[k],l,mid);
build(rs[k],mid+1,r);
}
}
void dfs(int x) {
SIZ[x]=1;bl[x]=cnt;son[x]=0;
update(rt[x],rt[fa[x]],1,LSH,p[x]);
for(int i=head[x]; i; i=nxt[i]) {
if(fa[x]!=to[i]) {
fa[to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]),SIZ[x]+=SIZ[to[i]];
if(SIZ[to[i]]>SIZ[son[x]]) son[x]=to[i];
}
}
}
void dfs(int x,int qtop) {
top[x]=qtop;
if(!son[x]) return;
dfs(son[x],qtop);
for(int i=head[x]; i; i=nxt[i]) {
if(fa[x]!=to[i]&&to[i]!=son[x]) dfs(to[i],to[i]);
}
}
int lca(int x,int y) {
while(top[x]!=top[y]) (dep[top[x]]>=dep[top[y]])?x=fa[top[x]]:y=fa[top[y]];
return dep[x]>dep[y]?y:x;
}
char ch[5];
int query(int u,int v,int lca,int lcafa,int l,int r,int kth) {
if(l==r)return l;
int sum=siz[ls[u]]+siz[ls[v]]-siz[ls[lca]]-siz[ls[lcafa]];
int mid=l+r>>1;
if(sum>=kth) return query(ls[u],ls[v],ls[lca],ls[lcafa],l,mid,kth);
else return query(rs[u],rs[v],rs[lca],rs[lcafa],mid+1,r,kth-sum);
}
int main() {T=rd();
n=rd();m=rd();q=rd();
ecnt=cnt=tot=LSH=0;
for(int i=1; i<=n; i++) scanf("%d",&p[i]),lsh[i]=p[i];
sort(lsh+1,lsh+1+n);
LSH=unique(lsh+1,lsh+1+n)-lsh-1;
for(int i=1; i<=n; i++) p[i]=lower_bound(lsh+1,lsh+1+LSH,p[i])-lsh;
for(int i=1,u,v; i<=m; i++)u=rd(),v=rd(),add(u,v),add(v,u);
build(rt[0],1,LSH);
for(int i=1; i<=n; i++) if(!SIZ[i]) root[++cnt]=i,dfs(i),dfs(i,i);
int x,y,k,lastans=0;
while(q--) {
scanf("%s",ch);
if(ch[0]=='Q') {
x=rd()^lastans,y=rd()^lastans,k=rd()^lastans;
int LCA=lca(x,y),LCAFA=fa[LCA];
printf("%d
",lastans=lsh[query(rt[x],rt[y],rt[LCA],rt[LCAFA],1,LSH,k)]);
}
else if(ch[0]=='L') {
x=rd()^lastans;y=rd()^lastans;
if(SIZ[root[bl[x]]]<SIZ[root[bl[y]]]) swap(x,y);
add(x,y),add(y,x);
cnt=bl[x];
SIZ[root[bl[x]]]+=SIZ[root[bl[y]]];dfs(x);dfs(x,top[x]);
}
}
}