永无乡包含 n n 座岛,编号从 到 n n ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 座岛排名,名次用 1 1 到 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛 a a 出发经过若干座(含 座)桥可以 到达岛 b b ,则称岛 和岛 b b 是连通的。
现在有两种操作:
x x 表示在岛 x x 与岛 之间修建一座新桥。
Q Q k k 表示询问当前与岛 连通的所有岛中第 k k 重要的是哪座岛,即所有与岛 连通的岛中重要度排名第 k k 小的岛是哪座,请你输出那个岛的编号。
查询第 大直接平衡树。连接就是合并两个平衡树。
并查集维护一下在不在一棵树中,注意并查集的按秩合并 和
treap
t
r
e
a
p
的启发式合并要同步,然后更改根那里记得写&.
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
typedef pair<int,int>par;
#define mp make_pair
inline int read(){
int x=0;char c=getchar();
while(c<'0'||c>'9')c=getchar();
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x;
}
int ma[MAXN];
int fa[MAXN],rk[MAXN];
inline int find(int x){
return x==fa[x]?x:fa[x]=find(fa[x]);
}
inline void merge_set(int x,int y){
if((x=find(x))==(y=find(y)))return;
if(rk[x]>rk[y])fa[y]=x,rk[x]+=rk[y];
else {
fa[x]=y;
rk[y]+=rk[x];
}
}
inline void makeset(int n){
for(int i=0;i<=n;i++)fa[i]=i,rk[i]=1;
}
struct treap{
int val[MAXN],prio[MAXN],lson[MAXN],rson[MAXN],size[MAXN],rt[MAXN],cnt;
inline void pushup(int o){
size[o]=size[lson[o]]+size[rson[o]]+1;
}
inline par split(int p,int x){
if(!x)return mp(0,p);
int l=lson[p],r=rson[p];
if(x<=size[l]){
par tem=split(l,x);
lson[p]=tem.second;pushup(p);return mp(tem.first,p);
}
par tem=split(r,x-size[l]-1);
rson[p]=tem.first;pushup(p);return mp(p,tem.second);
}
inline int merge(int x,int y){
if(!x){pushup(y);return y;}
if(!y){pushup(x);return x;}
if(prio[x]<prio[y]){
rson[x]=merge(rson[x],y);pushup(x);return x;
}
lson[y]=merge(x,lson[y]);pushup(y);return y;
}
inline int newnode(int x){
++cnt;
prio[cnt]=rand();val[cnt]=x;lson[cnt]=rson[cnt]=0;
size[cnt]=1;
return cnt;
}
int findsz(int Rt,int x){
int p=Rt,ans=0;
while(p){
if(val[p]<x)ans+=size[lson[p]]+1,p=rson[p];
else p=lson[p];
}
return ans;
}
void modify(int &a,int &b){//把a合并到b上
del(a,b);
a=b;
}
void del(int p,int &Rt){//将a上的所有节点pi删除插入到Rt上
if(lson[p])del(lson[p],Rt);
if(rson[p])del(rson[p],Rt);
lson[p]=rson[p]=0;size[p]=1;
ins(Rt,p);
}
void ins(int &Rt,int p){//修改rt
int sz=findsz(Rt,val[p]);
par t1=split(Rt,sz);
Rt=merge(merge(t1.first,p),t1.second);
}
void debug(int rt){
if(lson[rt])debug(lson[rt]);
printf("%d ",val[rt]);
if(rson[rt])debug(rson[rt]);
}
}T;
int n,m;
void Merge(int x,int y){
if(T.size[T.rt[fa[x]]]<=T.size[T.rt[fa[y]]])T.modify(T.rt[fa[x]],T.rt[fa[y]]);
else T.modify(T.rt[fa[y]],T.rt[fa[x]]);
merge_set(x,y);
}
void query(int x,int k){
//T.debug(T.rt[fa[x]]);puts("sm");
if(T.size[T.rt[fa[x]]]<k){
puts("-1");return;
}
par t1=T.split(T.rt[fa[x]],k-1);
par t2=T.split(t1.second,1);
printf("%d\n",ma[T.val[t2.first]]);
T.rt[fa[x]]=T.merge(t1.first,T.merge(t2.first,t2.second));
}
int main(){
srand(19260817);
n=read(),m=read();
makeset(n);
for(int i=1;i<=n;i++){
int tmp;
tmp=read();ma[tmp]=i;
T.rt[i]=T.newnode(tmp);
}
for(int i=1;i<=m;i++){
int x,y;
x=read();y=read();
if(fa[x]!=fa[y]){
Merge(x,y);/* puts("gg");
T.debug(T.rt[fa[y]]);*/
}
}
int q,x,y;
char opt[2];
q=read();
for(int i=1;i<=q;i++){
scanf("%s",opt);
x=read();y=read();
if(opt[0]=='Q'){
query(x,y);
}
else {
if(fa[x]!=fa[y]){
Merge(x,y);
}
}
}
return 0;
}