洛谷 [P3377] 左偏树(可并堆)
可并堆,就是可以合并的堆
注意并查集不能路径压缩,不然删除根节点时会出错
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;
const int MAXN = 105005;
int init() {
int rv = 0, fh = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') fh = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
rv = (rv<<1) + (rv<<3) + c - '0';
c = getchar();
}
return fh * rv;
}
int n, m;
struct LT{
struct node {
int l, r, val, dist, fa;
}a[MAXN];
int find(int x) {
if(x != a[x].fa) return find(a[x].fa);
return a[x].fa;
}
int merge(int u, int v) {
if(!u) return v;
if(!v) return u;
if(a[u].val > a[v].val || (a[u].val == a[v].val && u > v)) swap(u, v);
int &ul = a[u].l, &ur = a[u].r;
ur = merge(ur, v);
a[ur].fa = u;
if(a[ul].dist < a[ur].dist) swap(ur, ul);
a[u].dist = a[ur].dist + 1;
return u;
}
void input() {
a[0].dist = -1;
for(int i = 1; i <= n; i++) a[i].fa = i;
for(int i = 1; i <= n; i++) a[i].val = init();
}
void erase(int u) {
int ul = a[u].l, ur = a[u].r;
a[u].val = -1;
a[ul].fa = ul; a[ur].fa = ur;
merge(ul, ur);
}
void work() {
input();
for(int i = 1; i <= m; i++) {
int opt = init();
if(opt == 1){
int x = init(), y = init();
if(a[x].val == -1 || a[y].val == -1) continue;
int r1 = find(x), r2 = find(y);
if(r1 == r2) continue;
merge(r1, r2);
}else {
int x = init();
if(a[x].val == -1) {
printf("-1\n");continue;
}
int r1 = find(x);
printf("%d\n", a[r1].val);
erase(r1);
}
}
}
}lt;
int main() {
//freopen("in.txt", "r", stdin);
n = init(); m = init();
lt.work();
//fclose(stdin);
return 0;
}