有 n 隻猴子,每隻有初始戰力。進行 m 次操作:指定兩隻猴子 a, b 決鬥。規則如下:
-1v = v/2)並重新歸隊merge、insert、pop(刪除堆頂)皆為 O(log n)dist:右子樹距離 ≤ 左子樹距離,合併時若違反則交換左右子樹find 路徑壓縮id[x] 記錄群體 x 對應的左偏樹根節點編號初始化:
每隻猴子自成一群,建立單節點左偏樹
並查集 p[i] = i,id[i] = 對應樹節點
處理每次決鬥 (a, b):
x = find(a), y = find(b)
if x == y: 輸出 -1
else:
// 取出兩群最強猴子
u = top(id[x]); id[x] = pop(id[x]); id[x] = insert(id[x], u/2)
u = top(id[y]); id[y] = pop(id[y]); id[y] = insert(id[y], u/2)
// 合併群體與左偏樹
p[x] = y
id[y] = merge(id[x], id[y])
輸出 top(id[y])
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 300000 + 10;
int v[maxn], l[maxn], r[maxn], d[maxn];
int p[maxn], id[maxn];
int tot;
int find_set(int x) {
return p[x] == x ? x : p[x] = find_set(p[x]);
}
int merge(int x, int y) {
if (!x) return y;
if (!y) return x;
if (v[x] < v[y]) swap(x, y); // 大根堆
r[x] = merge(r[x], y);
if (d[l[x]] < d[r[x]]) swap(l[x], r[x]);
d[x] = d[r[x]] + 1;
return x;
}
int init_node(int val) {
++tot;
v[tot] = val;
l[tot] = r[tot] = d[tot] = 0;
return tot;
}
int insert(int root, int val) {
return merge(root, init_node(val));
}
int top(int root) { return v[root]; }
int pop(int root) { return merge(l[root], r[root]); }
int main() {
int n, m, u, a, b;
while (~scanf("%d", &n)) {
tot = 0;
for (int i = 1; i <= n; i++) {
p[i] = i;
id[i] = i;
}
for (int i = 1; i <= n; i++) {
scanf("%d", &u);
init_node(u); // 節點編號即 i
}
scanf("%d", &m);
while (m--) {
scanf("%d%d", &a, &b);
int x = find_set(a), y = find_set(b);
if (x == y) {
puts("-1");
} else {
int u = top(id[x]);
id[x] = pop(id[x]);
id[x] = insert(id[x], u / 2);
u = top(id[y]);
id[y] = pop(id[y]);
id[y] = insert(id[y], u / 2);
p[x] = y;
id[y] = merge(id[x], id[y]);
printf("%d\n", top(id[y]));
}
}
}
return 0;
}
O((n + m) log n),每次操作涉及常數次左偏樹合併/刪除O(n + m),節點數最多初始 n + 每次決鬥插入 2 個 = n + 2mn 個節點編號 1~n,後續 insert 需分配新編號(tot++)id[y]merge 時比較 v[x] < v[y] 交換,確保堆頂為最大值d[x] = d[r[x]] + 1,葉節點距離為 0,空節點距離視為 -1(陣列預設 0 需注意)輸入:
5 10 20 30 40 50 3 1 2 3 4 1 3
過程:
本題是左偏樹與並查集結合的經典模板題。關鍵在於:
id[] 陣列橋接兩者,實現群體到堆的映射掌握此模式,可解決所有「動態集合合併+查詢極值」類問題。