采用了jls的左偏树写法,非常好写...

额外用一个并查集维护集合关系即可,注意路径压缩。

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

#define LOG(...) fprintf (stderr, __VA_ARGS__)
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)(x).size())
#define ALL(x) (x).begin(), (x).end()

const int INF = 0x3f3f3f3f, N = 100005;
const LL INFL = 0x3f3f3f3f3f3f3f3fll;

int n, m, rt[N], cnt, f[N], a[N];
struct HeapNode {
    int w, ls, rs, sz;
    HeapNode (int w=0, int ls=0, int rs=0, int sz=0): w(w), ls(ls), rs(rs), sz(sz){}
}e[N];

int find (int x) {
    return x == f[x] ? f[x] : f[x] = find(f[x]);
}
int merge (int x, int y) {
    if (!x || !y) return x+y;
    if (e[x].w > e[y].w || (e[x].w == e[y].w && x > y)) swap(x, y);
    e[x].rs = merge(e[x].rs, y);
    if (e[e[x].rs].sz > e[e[x].ls].sz) swap(e[x].ls, e[x].rs);
    e[x].sz = e[e[x].rs].sz + 1;
    return x;
}
int main() {
#ifdef LiM_817
    double cl = clock();
    freopen ("input.txt", "r", stdin);
#endif


    scanf ("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        rt[i] = ++cnt; f[i] = i;
        int w; scanf ("%d", &w);
        a[i] = w;
        e[rt[i]] = (HeapNode) {w, 0, 0, 1};
    }

    while (m--) {
        int op, x, y;
        scanf ("%d%d", &op, &x);
        if (op == 1) {
            scanf ("%d", &y);
            if (a[x] == -1 || a[y] == -1) continue;
            x = find(x), y = find(y);
            rt[x] = merge(rt[x], rt[y]);
            f[y] = x;
        }
        else if (op == 2) {
            if (a[x] == -1) {
                puts("-1");
                continue;
            }
            int t = find(x);
            printf ("%d\n", e[rt[t]].w);
            a[rt[t]] = -1;
            rt[t] = merge(e[rt[t]].ls, e[rt[t]].rs);
        }
    }
#ifdef LiM_817
    cerr << fixed << setprecision(2) << "Time ellapsed: " << ((double)(clock() - cl) / CLOCKS_PER_SEC) << "s\n";
#endif
    return 0;
}
01-07 03:08