ZOJ 2334 Monkey King 是左偏樹的模板題,核心需維護集合關係,並查集極適合處理動態合併與查詢;同時需記錄每個節點所屬左偏樹的編號,以便快速存取堆頂元素。
find 操作。id[] 陣列:記錄每個集合代表元對應的左偏樹根節點編號。id[i] = i。(a, b):
find(a) == find(b),輸出 -1。// 左偏樹合併
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 _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
// 主流程
while (m--) {
scanf("%d%d", &a, &b);
int x = _find(a), y = _find(b);
if (x == y) { puts("-1"); continue; }
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]));
}
每次操作涉及常數次左偏樹合併與並查集查找,時間複雜度 O(log n),空間複雜度 O(n),完全滿足題目限制。
本題完美展示左偏樹與並查集結合處理動態集合合併與優先隊列操作的威力,是掌握進階資料結構的優質練習題。