简单的左偏堆,维护一个pos记录每一个节点的位置(方便删除),记录每一个堆的最优解,通过swap子树的方式来保证时间复杂度近似logn(度娘上有详解)可以参照某初中大佬 阿波罗2003 对可并堆的一些理解点击打开链接
下面是可并堆的代码实现,用类似动态开节点的方式进行操作
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int fa[maxn];
bool del[maxn];
struct Node{
int pos,val,dis;
Node *ls;
Node *rs;
}pool[maxn<<1],*tail=pool,*root[maxn<<1];
Node *newnode(int pos,int val){
Node *nd = ++tail;
nd->val=val;
nd->pos=pos;
nd->ls=nd->rs=0;
nd->dis=0;
return nd;
}
Node *merge(Node *n1,Node *n2){
if (!n1) return n2;
if (!n2) return n1;
if (n1->val>n2->val) swap(n1,n2);
n1->rs=merge(n1->rs,n2);
if (!n1->ls||n1->rs->dis>n1->ls->dis) swap(n1->ls,n1->rs);
if (!n1->rs){
n1->dis=0;
} else {
n1->dis=n1->rs->dis;
}
return n1;
}
int find(int x){
return x==fa[x]?x:find(fa[x]);
}
int n,m;
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
int x;
scanf("%d",&x);
root[i]=newnode(i,x);
fa[i]=i;
}
while (m--){
int ops;
scanf("%d",&ops);
if (ops==1){
int x,y;
scanf("%d%d",&x,&y);
if (del[x]||del[y]) continue;
int fx=find(x);
int fy=find(y);
if (fx==fy) continue;
fa[fx]=fy;
root[fy]=merge(root[fx],root[fy]);
} else {
int x;
scanf("%d",&x);
if (del[x]){
printf("-1\n");
continue;
}
int fx=find(x);
printf("%d\n",root[fx]->val);
del[root[fx]->pos]=1;
root[fx]=merge(root[fx]->ls,root[fx]->rs);
}
}
}
操作还是比较简单的,用处也比家广泛