左偏树是一种数据结构,板子都是蓝色的那种……
左偏树不像平衡树,它不是平衡的,甚至一条链也可能是左偏树。
左偏树可以用来维护堆,并且支持合并操作。
(以小根堆为例)
对于合并操作,我们取出两个左偏树较小的根作为合并后的左偏树的根,然后将此树的右子树和另一棵树合并,递归处理。
对于删除根,我们直接将其两颗子树合并即可。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int read()
{
int a = 0,x = 1;
char ch = getchar();
while(ch > '9' || ch < '0') {
if(ch == '-') x = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
a = a*10 + ch-'0';
ch = getchar();
}
return a*x;
}
const int N=1e6+7;
int n,m,ins[N];
struct node {
int fa,dist,rs,ls;
int val,id;
#define fa(x) arr[x].fa
#define dist(x) arr[x].dist
#define rs(x) arr[x].rs
#define ls(x) arr[x].ls
#define val(x) arr[x].val
#define id(x) arr[x].id
friend bool operator < (node a,node b) {return (a.val!=b.val)?a.val<b.val:a.id<b.id;}
friend bool operator > (node a,node b) { return !(a<b);}
}arr[N];
int find(int s)
{
//printf("%d ",s);
if(fa(s) == s) return s;
else return fa(s) = find(fa(s));
}
int merge(int a,int b)
{
if(!a || !b) return a|b;
if(arr[a] > arr[b]) swap(a,b);
fa(rs(a) = merge(rs(a),b)) = a;
if(dist(ls(a)) < dist(rs(a))) swap(ls(a),rs(a));
dist(a) = dist(rs(a)) + 1;
return a;
}
void print(int x)
{
if(x >= 10) print(x/10);
putchar('0'+x%10);
}
void del(int x)
{
print(val(x));putchar('
');
fa(x) = merge(ls(x),rs(x));
fa(fa(x)) = fa(x);
ins[x] = 0;
}
int main()
{
n = read(),m = read();
for(int i = 1;i <= n;i ++) {
arr[i].val = read(),ins[i] = 1,id(i) = i;
fa(i) = i;
}
for(int i = 1;i <= m;i ++) {
int op = read();
if(op == 1) {
int x = read(),y = read();
if(!ins[x] || !ins[y]) continue;
if(find(x) == find(y)) continue;
merge(find(x),find(y));
} else {
int x = read();
if(ins[x]) {
del(find(x));
} else puts("-1");
}
}
return 0;
}