Luogu P3377模板左偏树(可并堆)
Posted lim-817
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P3377模板左偏树(可并堆)相关的知识,希望对你有一定的参考价值。
采用了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
", 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
";
#endif
return 0;
}
以上是关于Luogu P3377模板左偏树(可并堆)的主要内容,如果未能解决你的问题,请参考以下文章