hdu1512 二项堆

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn = 100100;
int key[maxn],lef[maxn],sib[maxn],cnt[maxn],fa[maxn];
int get_fa(int x){
	int p=x;
	while(fa[x])x=fa[x];
	while(p!=x){
		int tmp=fa[p];
		fa[p]=x;
		p=tmp;
	}
	return x;
}
int top(int x){
	int ans=-1,p;
	while(x){
		if(key[x]>ans){ans=key[x];p=x;}
		x=sib[x];
	}
	return p;
}
void link(int x,int y){
	sib[x]=lef[y];
	lef[y]=x;
	cnt[y]++;
}
int merge(int x,int y){
	int tx=x,ty=y;
	int p,q;
	if(cnt[x]<=cnt[y]){p=x;x=sib[x];}
	else {p=y;y=sib[y];}
	q=p;
	while(x&&y){
		if(cnt[x]<=cnt[y]){sib[p]=x;x=sib[x];}
		else {sib[p]=y;y=sib[y];}
		p=sib[p];
	}
	if(x)sib[p]=x;
	if(y)sib[p]=y;
	p=q;
	int pre=0;
	int next=sib[p];
	while(next){
		if(cnt[p]!=cnt[next]||
			(sib[next]&&cnt[p]==cnt[sib[next]])){
			pre=p;
			p=next;
		}else if(key[p]>=key[next]){
			sib[p]=sib[next];
			link(next,p);
		}else{
			if(pre==0)q=next;
			else sib[pre]=next;
			link(p,next);
			p=next;
		}
		next=sib[p];
	}
	fa[tx]=fa[ty]=q;
	fa[q]=0;
	return q;
}
void maintain(int x){
	if(!x)return ;
	int p=0,ret=-1;
	for(int i=lef[x];i;i=sib[i]){
		if(key[i]>ret){
			p=i;
			ret=key[i];
		}
	}
	if(ret>key[x]){
		swap(key[p],key[x]);
		maintain(p);
	}
}


int main() {
	int n;
	while(~scanf("%d",&n)){
		for(int i=1;i<=n;i++){
			scanf("%d",&key[i]);
			lef[i]=sib[i]=cnt[i]=fa[i]=0;
		}
		int m;
		scanf("%d",&m);
		for(int i=0;i<m;i++){
			int a,b;
			scanf("%d%d",&a,&b);
			int x=get_fa(a);
			int y=get_fa(b);
			if(x==y)printf("-1\n");
			else{
				int p=top(x);
				int q=top(y);
				key[p]/=2;
				key[q]/=2;
				maintain(p);maintain(q);
				printf("%d\n",key[top(merge(x,y))]);
			}
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值