Solution
感觉自己没学懂。。。
(mathtt{unite}) 函数只是将 x 与 y 相连,不是它们的 f 相连!所以合并的时候应该将两棵树的根合并而不是直接合并。
另外删除的时候直接将 root 的 f 设置为最优儿子就行了,因为我们是用并查集进行维护。但这同时也要注意一个问题:将儿子的 f 设置为自己,不然会有死循环。
Code
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
const int N = 1e6 + 5;
int head[N], dot[N << 1], nxt[N << 1], cnt;
bool vis[N];
struct LT {
int f[N], son[N][2], val[N], dis[N];
void init(const int n) {
for(int i = 1; i <= n; ++ i) {
son[i][0] = son[i][1] = dis[i] = 0;
f[i] = i;
}
}
int Find(const int x) {return x == f[x] ? x : f[x] = Find(f[x]);}
bool cmp(const int x, const int y) {return Find(x) == Find(y);}
int unite(int x, int y) {
if(! x || ! y) return x + y;
if(val[x] > val[y]) swap(x, y);
son[x][1] = unite(son[x][1], y); f[son[x][1]] = x;
if(dis[son[x][0]] < dis[son[x][1]]) swap(son[x][0], son[x][1]);
dis[x] = dis[son[x][1]] + 1;
return x;
}
int del(const int x) {
int l = son[x][0], r = son[x][1];
son[x][0] = son[x][1] = dis[x] = 0;
f[l] = l; f[r] = r;
return unite(l, r);
}
void solve(const int x) {
int fa = Find(x);
printf("%d
", val[fa]);
vis[fa] = 1;
f[fa] = unite(son[f[fa]][0], son[f[fa]][1]);
f[f[fa]] = f[fa];
}
}T;
void addEdge(const int u, const int v) {
dot[++ cnt] = v; nxt[cnt] = head[u]; head[u] = cnt;
}
int read() {
int x = 0, f = 1; char s;
while((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
while(s >= '0' && s <= '9') {x = (x << 1) + (x << 3) + (s ^ 48); s = getchar();}
return x * f;
}
int main() {
int n = read(), m, x, y; char ch[5];
T.init(n);
for(int i = 1; i <= n; ++ i) T.val[i] = read();
m = read();
while(m --) {
scanf("%s", ch), x = read();
if(ch[0] == 'M') {
y = read();
if(vis[x] || vis[y]) continue;
int fx = T.Find(x), fy = T.Find(y);
if(fx != fy) T.f[fx] = T.f[fy] = T.unite(fx, fy);
}
else if(vis[x]) puts("0");
else T.solve(x);
}
return 0;
}