合并线段树模板。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 char ch[2];
 5 int n,m,q,sz,f[N],root[N],sum[2000005],ls[2000005],rs[2000005],v[N],id[N];
 6 inline void update(int x){
 7     sum[x]=sum[ls[x]]+sum[rs[x]];
 8 }
 9 inline int read(){
10     int x=0,f=1; char a=getchar();
11     while(a<'0' || a>'9') {if(a=='-') f=-1; a=getchar();}
12     while(a>='0' && a<='9') x=x*10+a-'0',a=getchar();
13     return x*f;
14 }
15 int fa(int x){
16     return f[x]!=x?f[x]=fa(f[x]):x;
17 }
18 void inser(int& x,int l,int r,int val){
19     x=++sz;
20     if(l==r) {sum[x]=1;return;}
21     int mid=(l+r)>>1;
22     if(val<=mid) inser(ls[x],l,mid,val); 
23     else inser(rs[x],mid+1,r,val);
24     update(x);
25 }
26 int merge(int x,int y){
27     if(!x) return y;
28     if(!y) return x;
29     ls[x]=merge(ls[x],ls[y]);
30     rs[x]=merge(rs[x],rs[y]);
31     update(x);
32     return x;
33 }
34 int query(int x,int l,int r,int k){
35     if(l==r) return l;
36     int mid=(l+r)>>1;
37     if(sum[ls[x]]>=k) return query(ls[x],l,mid,k);
38     else return query(rs[x],mid+1,r,k-sum[ls[x]]);
39 }
40 int main(){
41     n=read(); m=read();
42     for(int i=1;i<=n;i++) f[i]=i;
43     for(int i=1;i<=n;i++) v[i]=read();
44     for(int p,i=1;i<=n;i++) inser(root[i],1,n,v[i]),id[v[i]]=i;
45     for(int x,y,i=1;i<=m;i++) x=read(),y=read(),x=fa(x),y=fa(y),f[y]=x,root[x]=merge(root[x],root[y]);
46     q=read();
47     for(int x,y,i=1;i<=q;i++){
48         scanf("%s",ch); x=read(); y=read();
49         if(ch[0]=='Q'){
50             x=fa(x);
51             if(sum[root[x]]<y) {puts("-1");continue;}
52             else printf("%d\n",id[query(root[x],1,n,y)]);
53         }else{
54             x=fa(x); y=fa(y);
55             if(x!=y) f[y]=x,root[x]=merge(root[x],root[y]); 
56         }
57     }
58     return 0;
59 }