P1456 Monkey King

题目地址:P1456 Monkey King
一道挺模板的左偏树题

左偏树

优先队列在信息学竞赛中十分常见,在统计问题、最值问题、模拟问题和贪心问题等等类型的题目中,优先队列都有着广泛的应用。二叉堆是一种常用的优先队列,它编程简单,效率高,但如果问题需要对两个优先队列进行合并,二叉堆的效率就无法令人满意了。本文介绍的左偏树,可以很好地解决这类问题。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 6;
int n, m, f[N], a[N], l[N], r[N], d[N];

int get(int x) {
    if (x == f[x]) return x;
    return f[x] = get(f[x]);
}

inline int merge(int x, int y) {
    if (!x || !y) return x + y;
    if (a[x] < a[y]) swap(x, y);
    r[x] = merge(r[x], y);
    f[r[x]] = x;
    if (d[l[x]] < d[r[x]]) swap(l[x], r[x]);
    d[x] = d[r[x]] + 1;
    return x;
}

inline void pop(int x) {
    f[l[x]] = l[x], f[r[x]] = r[x];
    f[x] = merge(l[x], r[x]);
    l[x] = r[x] = 0;
}

inline void work() {
    d[0] = -1;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        f[i] = i;
        d[i] = l[i] = r[i] = 0;
    }
    cin >> m;
    while (m--) {
        int x, y;
        scanf("%d %d", &x, &y);
        int fx = get(x), fy = get(y);
        if (fx == fy) puts("-1");
        else {
            pop(fx), pop(fy);
            a[fx] >>= 1, a[fy] >>= 1;
            f[fx] = merge(fx, f[fx]);
            f[fy] = merge(fy, f[fy]);
            fx = get(fx), fy = get(fy);
            printf("%d\n", a[merge(fx,fy)]);
        }
    }
}

int main() {
    while (cin >> n) work();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/xht37/p/10415333.html