正解不是splay,但标解是splay+启发式合并。所谓的启发式合并就是把size小的往大的splay上加,复杂度是nlog2n。
由于无需知道根所以直接看此节点有没有父亲节点就可以判断是不是根。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define maxn 120110
int fa[maxn],tr[maxn][2],val[maxn],lab[maxn],f[maxn],siz[maxn],cnt;
int n,m,q[maxn];
int getfa(int x){return x == f[x] ? x : f[x] = getfa(f[x]);}
void pushup(int rt)
{
if (!rt) return;
int ls=tr[rt][0],rs=tr[rt][1];
siz[rt]=siz[ls]+siz[rs]+1;
}
void rotate(int x)
{
int l,r,y,z;
y=fa[x];z=fa[y];
if(tr[y][0]==x) l=0;
else l=1;r=l^1;
if(fa[y])
{
if(tr[z][0]==y) tr[z][0]=x;
else tr[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
tr[y][l]=tr[x][r];tr[x][r]=y;
pushup(y),pushup(x);
}
void splay(int x)
{
int z,y;
while(fa[x])
{
y=fa[x];z=fa[y];
if(fa[y])
{
if((tr[y][0]==x)^(tr[z][0]==y)) rotate(x);
else rotate(y);
}
rotate(x);
}
}
int select(int x,int rk)
{
int l=tr[x][0],r=tr[x][1];
int rak=siz[l]+1;
if(rak==rk) return x;
if(rak>rk) return select(l,rk);
else return select(r,rk-rak);
}
void insert(int &t,int anc,int now)
{
if (t == 0)
{
t = now;
fa[t] = anc;
siz[t] = 1;
splay(t);
return;
}
if (val[now] <= val[t]) insert(tr[t][0],t,now);
else insert(tr[t][1],t,now);
pushup(t);
}
int query(int a,int k)
{
if(siz[a]<k) return -1;
else return select(a,k);
}
void update(int a,int b)
{
splay(a),splay(b);
if(siz[a]>siz[b]) swap(a,b);
//printf("%d %d\n",siz[root[getfa(a)]],siz[root[getfa(b)]]);
int head = 0,tail = 1;
q[0] = b;q[1] = a;
while (head < tail)
{
int a = q[++ head];
if (tr[a][0]) q[++ tail] = tr[a][0];
if (tr[a][1]) q[++ tail] = tr[a][1];
tr[a][0] = tr[a][1] = 0;
insert(q[head - 1],0,a);
}
}
int main()
{
int a,b;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
f[i]=i;siz[i]=1;
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
if(getfa(a)!=getfa(b))
{
update(a,b);
f[f[a]]=f[b];
}
}
int op;char st[10];
scanf("%d",&op);
while(op--)
{
scanf("%s%d%d",st,&a,&b);
if(st[0]=='Q')
{
splay(a);
printf("%d\n",query(a,b));
}
else
{
if(getfa(a)!=getfa(b))
{
update(a,b);f[f[a]]=f[b];
}
}
}
return 0;
}
/*
5 1
4 3 2 5 1
1 2
7
Q 3 2
Q 2 1
B 2 3
B 1 5
Q 2 1
Q 2 4
Q 2 3
*/