學了線段樹合併以後這題感覺瞬間水了,標籤是平衡樹,平衡樹合併還沒學的很會,不過線段樹合併絕對是最好寫的
用並查集維護連通性。注意 合併的時候並查集要與線段樹合併一致 假如fa[a]=b 那麼就要把a合併到b上面去
另外的求第k大就是基礎操作了
#include<bits/stdc++.h>
#define R register int
using namespace std;
const int N = 1e5+10;
int fa[N],rt[N],lc[N*40],rc[N*40],sum[N*40],n,m,tot,q,val[N];
inline int in(){
R w=0,x=0;char c=0;
while(c<'0'||c>'9') w|=c=='-',c=getchar();
while(c<='9'&&c>='0') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return w?-x:x;
}
void update(R &o,R l,R r,R pos){
o=++tot;sum[o]++;
if(l==r) return;
R mid = l+r>>1;
if(pos<=mid) update(lc[o],l,mid,pos);
else update(rc[o],mid+1,r,pos);
}
int merge(R x,R y){
if(!x||!y) return x+y;
sum[x]+=sum[y];
lc[x]=merge(lc[x],lc[y]);
rc[x]=merge(rc[x],rc[y]);
return x;
}
int kth(R o,R l,R r,R k){
if(l==r) return l;
R mid = l+r>>1;
if(sum[lc[o]]>=k) return kth(lc[o],l,mid,k);
else return kth(rc[o],mid+1,r,k-sum[lc[o]]);
}
int getfa(int x){
return x==fa[x]?x:fa[x]=getfa(fa[x]);
}
int main(){
n=in();m=in();
for(R i = 1; i <= n; i++){
R x;
x=in();
update(rt[i],1,n,x);
val[x]=i;
fa[i]=i;
}
for(R i = 1; i <= m; i++){
R u,v;
u=in(),v=in();
R x=getfa(u),y=getfa(v);
if(x!=y){
fa[y]=x;
rt[x]=merge(rt[x],rt[y]);
}
}
q=in();
char op[3];
R x,y;
for(R i = 1; i <= q; i++){
scanf("%s",op);
x=in(),y=in();
if(op[0]=='Q'){
x=getfa(x);
if(sum[rt[x]]<y) puts("-1");
else printf("%d\n",val[kth(rt[x],1,n,y)]);
}else{
R u=getfa(x),v=getfa(y);
if(u!=v){
fa[v]=u;
rt[u]=merge(rt[u],rt[v]);
}
}
}
return 0;
}