第一次写线段树合并
一开始完全自己yy板子写得特别丑
一开始完全自己yy板子写得特别丑
后来看到了别人的板子发现又简洁又好写
//Never Say Never until the very end.
#include <iostream>
#include <cstdio>
#define N 100050
using namespace std;
int tr[20*N],ls[20*N],rs[20*N],fa[N],root[N],ys[N],hash[N];
int n,m,cnt,v,ans;
int get(int x) { if (fa[x] == x) return x; else return (fa[x] = get(fa[x]));}
void build(int l,int r,int t) {
tr[t]++;
if (l == r) return ;
int mid = (l + r) / 2;
if (v <= mid)
ls[t] = ++cnt , build(l,mid,cnt);
else
rs[t] = ++cnt , build(mid+1,r,cnt);
}
int merge(int x,int y) {
if (x == 0 || y == 0) return x+y;
ls[x] = merge(ls[x],ls[y]);
rs[x] = merge(rs[x],rs[y]);
tr[x] = tr[ ls[x] ] + tr[ rs[x] ];
return x;
}
void query(int l,int r,int t,int k) {
if (l == r) { ans = l; return ;}
int mid = (l + r) / 2;
if (tr[ ls[t] ] >= k)
query(l,mid,ls[t],k);
else
query(mid+1,r,rs[t],k - tr[ ls[t] ]);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&ys[i]) , hash[ys[i]] = i;
//cnt = 1;
for (int i=1;i<=n;i++) fa[i] = i;
for (v=1;v<=n;v++) root[v] = cnt+1 , build(1,n,++cnt);
for (int i=1;i<=m;i++) {
int u,v;
scanf("%d%d",&u,&v);
u = ys[u];
v = ys[v];
if (get(u) != get(v)) {
merge( root[ get(u) ] , root[ get(v) ] );
fa[ get(v) ] = get(u);
}
}
int q;
scanf("%d",&q);
for (int i=1;i<=q;i++) {
char cmd[10]; int a,b;
scanf("%s%d%d",cmd+1,&a,&b);
a = ys[a];
if (cmd[1] == 'B') {
b = ys[b];
if (get(a) != get(b)) {
merge(root[ get(a) ] , root[ get(b) ]);
fa[ get(b) ] = get(a);
}
} else {
if (tr[ root[ get(a) ] ] < b) {printf("-1\n");continue;}
query(1,n,root[ get(a) ] , b);
printf("%d\n",hash[ans]);
}
}
return 0;
}