傳送門:http://www.lydsy.com/JudgeOnline/problem.php?id=1455
題目描述:羅馬皇帝很喜歡玩殺人遊戲。 他的軍隊裏面有
題解: 是個左偏樹板子題,只需要一個 merge 操作,要注意的是刪除的時候要把刪除節點父親變成 merge 後的節點並把那個節點的父親賦爲自己。
#include<bits/stdc++.h>
const int N = 1e6 + 10;
template <typename T> void read(T &x) {
x = 0; char c = getchar();
for (; !isdigit(c); c = getchar());
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
}
struct Node{
int val, h;
Node *lc, *rc;
}Nil[N];
int n, m, x, y, fa[N];
bool killed[N];
char op[5];
int find(int x) {return fa[x] == x ? x : find(fa[x]);}
Node *merge(Node *a, Node *b) {
if (a == Nil) return b;
if (b == Nil) return a;
if (a -> val > b -> val) std::swap(a, b);
a -> rc = merge(a -> rc, b);
if (a -> lc -> h < a -> rc -> h) std::swap(a -> lc, a -> rc);
a -> h = a -> rc -> h + 1;
return a;
}
int main() {
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
read(n);
for (int i = 1; i <= n; i++)
read((Nil+i) -> val), fa[i] = i,
(Nil+i) -> lc = Nil, (Nil+i) -> rc = Nil, (Nil+i) -> h = 1;
Nil -> lc = Nil; Nil -> rc = Nil;
read(m);
while (m--) {
scanf("%s", op);
if (op[0] == 'M') {
read(x); read(y);
if (killed[x] || killed[y] || (x = find(x)) == (y = find(y))) continue;
fa[x] = fa[y] = merge(Nil+x, Nil+y) - Nil;
}else {
read(x);
if (killed[x]) {printf("0\n"); continue;}
printf("%d\n", (Nil + (x = find(x))) -> val);
killed[x] = 1;
fa[fa[x] = merge((Nil + x) -> lc, (Nil + x) -> rc) - Nil] = fa[x];
}
}
return 0;
}