1. 程式人生 > 其它 >「學習筆記」左偏樹

「學習筆記」左偏樹

//合併 
int merge(int x,int y){
	if(!x || !y) return x|y;
	if(t[x].key>t[y].key) swap(x,y);
	t[t[x].rs=merge(t[x].rs,y)].fa=x;
	if(t[t[x].rs].d>t[t[x].ls].d) swap(t[x].ls,t[x].rs);
	t[x].d=t[t[x].rs].d+1;
	return x;
}
//構建
void build(){
	int l=1,r=n;
	for(int i=1;i<n;i++){//可證只有n-1次合併
		h[++r]=merge(h[l],h[l+1]);
		l+=2;
	}
}
//刪除任意結點(pop)
void pushup(int x){
	if(!x) return;
	if(t[x].d!=t[t[x].rs].d+1){
		t[x].d=t[t[x].rs].d+1;
		pushup(t[x].fa);
	}
}

int merge(int x,int y){
	if(!x || !y) return x|y;
	if(t[x].key>t[y].key) swap(x,y);
	t[t[x].rs=merge(t[x].rs,y)].fa=x;
	if(t[t[x].rs].d>t[t[x].ls].d) swap(t[x].ls,t[x].rs);
	pushup(x);
	return x;
}

int pop(int x){
	return merge(t[x].ls,t[x].rs);
}
//整個堆加/減去一個值、乘上一個正數,在根上打標記,下傳
int merge(int x,int y){
	if(!x || !y) return x|y;
	if(t[x].key>t[y].key) swap(x,y);
	pushdown(x);
	t[t[x].rs=merge(t[x].rs,y)].fa=x;
	if(t[t[x].rs].d>t[t[x].ls].d) swap(t[x].ls,t[x].rs);
	pushup(x);
	return x;
}

int pop(int x){
	pushdown(x);
	return merge(t[x].ls,t[x].rs);
}
//隨機合併
int merge(int x,int y){
	if(!x || !y) return x|y;
	if(t[x].key>t[y].key) swap(x,y);
	if(rand()&1) swap(t[x].ls,t[x].rs);
	t[x].ls=merge(t[x].ls,y);
	return x;
}
//最終的板子
void pushup(int x){
	if(!x) return;
	if(t[x].d!=t[t[x].rs].d+1){
		t[x].d=t[t[x].rs].d+1;
		pushup(t[x].fa);
	}
}

int merge(int x,int y){
	if(!x || !y) return x|y;
	if(t[x].key>t[y].key) swap(x,y);
	pushdown(x);
	t[t[x].rs=merge(t[x].rs,y)].fa=x;
	if(t[t[x].rs].d>t[t[x].ls].d) swap(t[x].ls,t[x].rs);
	pushup(x);
	return x;
}

int pop(int x){
	pushdown(x);
	return merge(t[x].ls,t[x].rs);
}