题目大意
n个节点的带权树,初始m条边,q个操作,支持查询x到y间k小值,连边两个操作 n,m,q<=8*10^4
$Kth$自然想到主席树,小子树接到大子树后暴力合并就好了
$Dfs$时顺便以父节点为前驱继承节点建树
Ps:输入里的testcase只是测试点编号,不是该测试点的多组数据
My complete code:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
using namespace std;
typedef long long LL;
const LL maxn=200000;
inline LL read(){
LL x=0,f=1; char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1; c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0'; c=getchar();
}return x*f;
}
struct node{
LL to,next;
}dis[maxn];
LL T,n,m,q,num,nod,cnt;
LL head[maxn],val[maxn],b[maxn],father[maxn],inc[maxn][25];
LL dep[maxn],date[maxn<<7],lt[maxn<<7],rt[maxn<<7],root[maxn],size[maxn];
bool visit[maxn];
inline void Add(LL u,LL v){
dis[++num]=(node){v,head[u]}; head[u]=num;
}
inline LL Two_part(LL x){
return (lower_bound(b+1,b+1+cnt,val[x])-b);
}
LL Find(LL x){
return father[x]=father[x]==x?x:Find(father[x]);
}
void Update(LL &now,LL pre,LL l,LL r,LL c){
now=++nod;
date[now]=date[pre]+1;
LL mid=(l+r)>>1;
if(l==r)
return;
if(c<=mid){
Update(lt[now],lt[pre],l,mid,c);
rt[now]=rt[pre];
}else{
Update(rt[now],rt[pre],mid+1,r,c);
lt[now]=lt[pre];
}
}
void Dfs(LL u,LL fa,LL R){
dep[u]=dep[fa]+1;
inc[u][0]=fa;
for(LL i=1;i<=20;++i)
inc[u][i]=inc[inc[u][i-1]][i-1];
size[R]++;
father[u]=fa;
Update(root[u],root[fa],1,cnt,Two_part(u));
for(LL i=head[u];i;i=dis[i].next){
LL v=dis[i].to;
if(v==fa)
continue;
Dfs(v,u,R);
}
visit[u]=true;
}
inline LL LCA(LL x,LL y){
if(dep[x]<dep[y])
swap(x,y);
for(LL i=20;i>=0;--i)
if(dep[inc[x][i]]>=dep[y])
x=inc[x][i];
if(x==y)
return x;
for(LL i=20;i>=0;--i)
if(inc[x][i]!=inc[y][i])
x=inc[x][i],
y=inc[y][i];
return inc[x][0];
}
LL query(LL x,LL y,LL lca,LL fa,LL l,LL r,LL c){
LL sum=date[lt[x]]+date[lt[y]]-date[lt[fa]]-date[lt[lca]];
LL mid=(l+r)>>1;
if(l==r)
return b[l];
if(c<=sum)
return query(lt[x],lt[y],lt[lca],lt[fa],l,mid,c);
else
return query(rt[x],rt[y],rt[lca],rt[fa],mid+1,r,c-sum);
}
int main(){
T=read();
T=1;
while(T--){
n=read(); m=read(); q=read();
for(LL i=1;i<=n;++i){
val[i]=read();
b[i]=val[i];
}
sort(b+1,b+1+n);
cnt=unique(b+1,b+1+n)-b-1;
for(LL i=1;i<=m;++i){
LL u=read(),v=read();
Add(u,v); Add(v,u);
}
for(LL i=1;i<=n;++i)
if(!visit[i]){
Dfs(i,0,i);
father[i]=i;
}
LL last_ans=0;
for(LL i=1;i<=q;++i){
char c;
LL x,y,k;
scanf(" %c",&c);
if(c=='Q'){
x=read()^last_ans;
y=read()^last_ans;
k=read()^last_ans;
LL lca=LCA(x,y);
LL fa=inc[lca][0];
printf("%lld
",last_ans=query(root[x],root[y],root[lca],root[fa],1,cnt,k));
}else{
x=read()^last_ans;
y=read()^last_ans;
Add(x,y); Add(y,x);
LL fx=Find(x),fy=Find(y);
if(size[fx]>size[fy]){
swap(fx,fy);
swap(x,y);
}
Dfs(x,y,fy);
}
}
}
return 0;
}