题目链接
启发式合并就是暴力合并把小的合并到大的里,一个一个插进去。
并查集维护连通性,同时保证并查集的根就是所在Splay的根,这样能省去很多操作。
#include <cstdio>
#include <algorithm>
using namespace std;
inline int read(){
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
const int MAXN = 100010;
struct SplayTree{
int ch[2], fa, val, size;
}t[MAXN];
int num, root, n, m, f[MAXN];
int find(int x){
return f[x] == x ? x : f[x] = find(f[x]);
}
void pushup(int u){
t[u].size = t[t[u].ch[0]].size + t[t[u].ch[1]].size + 1;
}
void rotate(int x){
int y = t[x].fa;
int z = t[y].fa;
int k = t[y].ch[1] == x;
t[z].ch[t[z].ch[1] == y] = x;
t[x].fa = z;
t[y].ch[k] = t[x].ch[k ^ 1];
t[t[x].ch[k ^ 1]].fa = y;
t[x].ch[k ^ 1] = y;
t[y].fa = x;
pushup(y);
pushup(x);
}
void Splay(int x, int goal){
while(t[x].fa){
int y = t[x].fa, z = t[y].fa;
if(z)
/**/ (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y);
rotate(x);
}
if(goal == 0) root = x;
}
inline int findKth(int k){
int u = root;
while(1){
if(t[t[u].ch[0]].size >= k) u = t[u].ch[0];
else if(t[t[u].ch[0]].size == k - 1) return u;
else k -= t[t[u].ch[0]].size + 1, u = t[u].ch[1];
}
}
int next(int x, int mode){
int u = t[x].ch[mode];
while(t[u].ch[!mode]) u = t[u].ch[!mode];
return u;
}
int a, b;
char c;
void insert(int x){
int u = root, fa = 0;
while(u) fa = u, u = t[u].ch[t[x].val > t[u].val];
t[fa].ch[t[x].val > t[fa].val] = x;
t[x].fa = fa;
Splay(x, 1);
}
void merge(int u){
if(t[u].ch[0]) merge(t[u].ch[0]);
if(t[u].ch[1]) merge(t[u].ch[1]);
t[u].ch[0] = t[u].ch[1] = 0; insert(u);
}
int T;
int main(){
n = read(); m = read();
for(int i = 1; i <= n; ++i)
t[i].val = read(), t[i].size = 1, f[i] = i;
for(int i = 1; i <= m; ++i){
a = read(); b = read();
int x = find(a), y = find(b);
if(x == y) continue;
if(t[x].size > t[y].size){
f[y] = x;
root = x; merge(y); Splay(x, 0);
}
else{
f[x] = y;
root = y; merge(x); Splay(y, 0);
}
}
T = read();
for(int i = 1; i <= T; ++i){
c = getchar(); while(c != 'Q' && c != 'B') c = getchar();
a = read(); b = read();
if(c == 'B'){
int x = find(a), y = find(b);
if(x == y) continue;
if(t[x].size > t[y].size){
f[y] = x;
root = x; merge(y); Splay(x, 0);
}
else{
f[x] = y;
root = y; merge(x); Splay(y, 0);
}
}
else{
root = find(a);
if(t[root].size < b) printf("%d
", -1);
else printf("%d
", findKth(b));
}
}
return 0;
}