平衡树(BST)

有关平衡树

说实话,好久没有打平衡树,现在手非常的生疏

所以时隔多年,我要重新捡起我的平衡树板子来,特此重新敲一遍

额,临时起意,我认为之前写的板子还挺符合我的心意的,我决定就用之前的了......

所以我就将几种平衡树写在这里

Splay

这个复杂度我也不会分析,好像是啥势能分析

反正没事就\(splay\)一下,就快起来了

code
struct node1{
	int son[2],fa;
	int siz,val,cnt;
}a[N*100];
int rt[N*4],seg;
int v[N],maxn;
struct Splay{
	inline int get(int x){
		return x==a[a[x].fa].son[1];
	}
	inline void pushup(int x){
		a[x].siz=a[a[x].son[0]].siz+a[a[x].son[1]].siz+a[x].cnt;
	}
	void rotate(int x){
		int y=a[x].fa,z=a[y].fa;
		int xpos=get(x),ypos=get(y);
		a[z].son[ypos]=x;
		a[x].fa=z;
		a[y].son[xpos]=a[x].son[xpos^1];
		a[a[x].son[xpos^1]].fa=y;
		a[x].son[xpos^1]=y;
		a[y].fa=x;
		pushup(y);
		pushup(x);
	}
	void splay(int &root,int x,int goal){
		while(a[x].fa!=goal){
			int y=a[x].fa,z=a[y].fa;
			int xpos=get(x),ypos=get(y);
			if(z!=goal)
				if(xpos==ypos)rotate(y);
				else rotate(x);
			rotate(x);
		}
		if(goal==0)root=x;
	}
	void ins(int &root,int x){
		int u=root,fa=0;
		while(u&&a[u].val!=x){
			fa=u;
			u=a[u].son[x>a[u].val];
		}
		if(u)a[u].cnt++;
		else{
			u=++seg;
			if(fa)a[fa].son[x>a[fa].val]=u;
			a[u].val=x;
			a[u].siz=a[u].cnt=1;
			a[u].fa=fa;
			a[u].son[0]=a[u].son[1]=0;
		}
		splay(root,u,0);
	}
	void find(int &root,int x){
		int u=root;
		while(x!=a[u].val)
			u=a[u].son[x>a[u].val];
		splay(root,u,0);
	}
	void del(int &root,int x){
		find(root,x);
		if(a[root].cnt>1){
			a[root].cnt--;
			pushup(root);
			return ;
		}
		if(!a[root].son[0]){
			root=a[root].son[1];
			pushup(root);
			return ;
		}
		if(!a[root].son[1]){
			root=a[root].son[0];
			pushup(root);
			return ;
		}
		int u=root;
		u=a[u].son[0];
		while(a[u].son[1])
			u=a[u].son[1];
		splay(root,u,root);
		a[a[root].son[1]].fa=u;
		a[u].son[1]=a[root].son[1];
		a[a[root].son[0]].fa=0;
		root=u;
		pushup(root);
		return ;
	}
	int getpre(int &root,int x){
		ins(root,x);
		int u=root;
		u=a[u].son[0];
		while(a[u].son[1])
			u=a[u].son[1];
		del(root,x);
		return a[u].val;
	}
	int getnxt(int &root,int x){
		ins(root,x);
		int u=root;
		u=a[u].son[1];
		while(a[u].son[0])
			u=a[u].son[0];
		del(root,x);
		return a[u].val;
	}
}sp;

FHQ Treap

这个好说,因为随机出来的\(rnd\)可以保证这颗树是平衡的

这里是我的随机数

于是,我们只需要不断地掰开-插入-合并-掰开-删除-合并

code
int merge(int x,int y){
	if(!x||!y)return x+y;
	if(a[x].rnd>a[y].rnd){
		a[x].r=merge(a[x].r,y);
		pushup(x);
		return x;
	}
	else{
		a[y].l=merge(x,a[y].l);
		pushup(y);
		return y;
	}
}
void split(int r,int pos,int &x,int &y){
	if(!r){
		x=y=0;
		return ;
	}
	if(a[a[r].l].siz>=pos){
		y=r;
		split(a[r].l,pos,x,a[r].l);
		pushup(r);
	}
	else{
		x=r;
		split(a[r].r,pos-a[a[r].l].siz-1,a[r].r,y);
		pushup(r);
	}
}
void ins(int &r,int pos,int val){
	int x=0,y=0,z=0;
	split(r,pos-1,x,y);
	newnode(z,val);
	r=merge(merge(x,z),y);
}
void del(int &r,int pos){
	int x=0,y=0,z=0;
	split(r,pos,x,z);
	split(x,pos-1,x,y);
	y=merge(a[y].l,a[y].r);
	r=merge(merge(x,y),z);
}

还有这个放着当古董的Treap

这个真的不如无旋的好写,也不如无旋的好用,而且不能可持久化,说白了就是废物一个

code
#define lc a[x].l
#define rc a[x].r
const int N=100005;
int n;
struct node{
	int l,r;
	int val,dat;
	int cnt,siz;
}a[N];
int seg,root;
int inf=0x3f3f3f3f;
int newdo(int val){
	a[++seg].val=val;
	a[seg].dat=rand();
	a[seg].cnt=a[seg].siz=1;
	return seg;
}
void pushup(int x){
	a[x].siz=a[lc].siz+a[rc].siz+a[x].cnt;
}
void build(){
	newdo(-inf);
	newdo(inf);
	root=1;
	a[1].r=2;
	pushup(root);
}
void zrg(int &x){
	int q=a[x].l;
	a[x].l=a[q].r;
	a[q].r=x;
	x=q;
	pushup(rc);
	pushup(x);
}
void zlg(int &x){
	int q=a[x].r;
	a[x].r=a[q].l;
	a[q].l=x;
	x=q;
	pushup(lc);
	pushup(x);
}
void insert(int &x,int val){
	if(x==0){
		x=newdo(val);
		return ;
	}
	if(val==a[x].val){
		a[x].cnt++;
		pushup(x);
		return ;
	}
	if(a[x].val>val){
		insert(lc,val);
		if(a[lc].dat>a[x].dat)zrg(x);
	}
	else{
		insert(rc,val);
		if(a[rc].dat>a[x].dat)zlg(x);
	}
	pushup(x);
}
int getpre(int val){
	int ret=1;
	int x=root;
	while(x){
		if(val==a[x].val){
			if(a[x].cnt>1)return val;
			if(lc>0){
				x=lc;
				while(rc>0)x=rc;
				ret=x;
			}
			break;
		}
		if(val>a[x].val and a[x].val>a[ret].val)ret=x;
		if(a[x].val>val)x=lc;
		else x=rc;
	}
	return a[ret].val;
}
int getnxt(int val){
	int ret=2;
	int x=root;
	while(x){
		if(val==a[x].val){
			if(a[x].cnt>1)return val;
			if(rc>0){
				x=rc;
				while(lc>0)x=lc;
				ret=x;
			}
			break;
		}
		if(a[x].val>val and a[ret].val>a[x].val)ret=x;
		if(a[x].val>val)x=lc;
		else x=rc;
	}
	return a[ret].val;
}
posted @ 2021-12-11 21:15  fengwu2005  阅读(68)  评论(0编辑  收藏  举报