线段树合并
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn], id[maxn], prt[maxn], root[maxn];
char s[5];
int tot;
struct node{ int l, r, sum; } tree[maxn*20];
inline int read()
{
int s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9'){ (s *= 10) += ch-'0'; ch = getchar(); }
return s*f;
}
int getpa(int x){ return prt[x] == x ? x : prt[x] = getpa(prt[x]); }
void update(int &rt,int num,int l,int r)
{
if(!rt){
rt = ++tot;
tree[rt].l = tree[rt].r = tree[rt].sum = 0;
}
tree[rt].sum++;
if(l == r) return ;
int mid = (l+r)>>1;
if(mid >= num) update(tree[rt].l,num,l,mid);
else update(tree[rt].r,num,mid+1,r);
//tree[rt].sum = tree[tree[rt].l].sum+tree[tree[rt].r].sum;
}
int query(int rt,int num,int l,int r)
{
if(l == r) return l;
int mid = (l+r)>>1, d = tree[tree[rt].l].sum;
if(d >= num) return query(tree[rt].l,num,l,mid);
return query(tree[rt].r,num-d,mid+1,r);
}
int Merge(int x,int y)
{
if(!x) return y;
if(!y) return x;
tree[x].l = Merge(tree[x].l,tree[y].l);
tree[x].r = Merge(tree[x].r,tree[y].r);
tree[x].sum = tree[tree[x].l].sum+tree[tree[x].r].sum;
return x;
}
int main()
{
int n, m, x, y;
n = read(); m = read();
for(int i = 1; i <= n; i++){
a[i] = read();
id[a[i]] = i; prt[i] = i;
}
for(int i = 1; i <= m; i++){
x = read(); y = read();
prt[getpa(x)] = getpa(y);
}
for(int i = 1; i <= n; i++){
update(root[getpa(i)],a[i],1,n);
}
m = read();
while(m--){
scanf("%s",s);
x = read(); y = read();
if(s[0] == 'Q'){
int p = getpa(x);
if(tree[root[p]].sum < y){
printf("-1\n"); continue;
}
printf("%d\n",id[query(root[p],y,1,n)]);
}
else{
int p = getpa(x), q = getpa(y);
if(p != q){
if(tree[root[p]].sum > tree[root[q]].sum){
swap(p,q);
}
prt[p] = q;
root[q] = Merge(root[p],root[q]);
}
}
}
return 0;
}