數據結構入門7—左偏樹

一種可並堆,具有左偏性質。每個點有一個距離。

距離則是如下定義的: 

節點i稱爲外節點(externalnode),當且僅當節點i的左子樹或右子樹爲空( left(i) = NULL或right(i) = NULL );節點i的距離(dist(i))是節點i到它的後代中,最近的外節點所經過的邊數。特別的,如果節點i本身是外節點,則它的距離爲0;而空節點的距離規定爲-1 (dist(NULL) =-1)。
 左偏樹滿足下面兩條基本性質: 
1、堆性質
2、節點的左子節點的距離不小於右子節點的距離。 即dist(left(i))≥dist(right(i)) (左偏性質)。性質2是爲了使我們可以以更小的代價(時間複雜度較小)插入節點或刪除最小節點操作後維持堆性質。

左偏樹的左右子樹也是左偏樹。如果不滿足左偏條件,則將左右兒子交換。

模板題(洛谷)   模板題(bzoj1455)

bzoj1455代碼:

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e6+10;
int n,m,fa[maxn],num[maxn],son[maxn][2],len[maxn];

int aa;char cc;
int read() {
	aa=0;cc=getchar();
	while(cc<'0'||cc>'9') cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	return aa;
}

int find(int x) {
	return x==fa[x]? x:find(fa[x]);
}

int merge(int x,int y) {
	if(!x||!y) return len[x]? x:y;
	if(num[x]>num[y]||(num[x]==num[y]&&y<x)) swap(x,y);
	if(son[x][1]) son[x][1]=merge(son[x][1],y);
	else son[x][1]=y;
	fa[son[x][1]]=x;
	if(!son[x][0]||len[son[x][1]]>len[son[x][0]]) swap(son[x][0],son[x][1]);
	len[x]=len[son[x][1]]+1;
	return x;
}

void del(int x) {
	if(!len[x]) {
		printf("0\n");
		return;
	}
	printf("%d\n",num[x]);
	fa[son[x][0]]=son[x][0];fa[son[x][1]]=son[x][1];
	if(son[x][1]&&son[x][0]) merge(son[x][0],son[x][1]);
	len[x]=0;son[x][0]=son[x][1]=0;
}

int main() {
	n=read();
	for(int i=1;i<=n;++i) fa[i]=i;
	for(int i=1;i<=n;++i) num[i]=read(),len[i]=1;
	char x;int y,z;m=read();
	for(int i=1;i<=m;++i) {
		x=getchar();
		while(x<'A'||x>'Z') x=getchar();
		y=read();y=find(y);
		if(x=='M') {
			z=read(); z=find(z);
			if(len[y]&&len[z]&&(y!=z)) merge(y,z);
		}
		else del(y);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章