左偏树 可并堆 bzoj1455/p1456

简单的左偏堆,维护一个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);
		}
	}
}

操作还是比较简单的,用处也比家广泛

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值