ZKW Splay

来宣传我大ZKW Splay.

没错这就是我说的Splay的奇怪姿势,貌似很少人知道?

据某论文所说常数是一般Splay的一半(没记错的话233).


大多数Splay自底向上,而我大ZKW Splay自顶向下.

基本操作是“zig”和“zigzig”,分别为“单旋”和“双旋”.

核心操作为search,select,所有的操作在root点展开.

search是在树上查找满足大小条件的一个点.

search时,从根节点向下走,之前经过的点,连同它的另一子树,都挂到一个链表上(像晾毛巾一样).

当根节点为要找的点时,停下来,这时候暴力把晾起来的“毛巾”挂回去.


select是在树上查找第k大的点.

原理和search相似.


用神奇的缩行可以把行数压在八、九十行(附带插入删除第k大).

由于,每次search,select操作会使树的形态发生变化,所以不能可持久化.

虽然自顶向下但也可以支持LCT.


最后 :

onst int oo=(1LL << 31)-1;
struct node {
	int key,size;
	node *c[2];
	node(): key(0),size(0){c[0]=c[1]=this;}
	node(int kk,node* c0,node* c1): key(kk){c[0]=c0;c[1]=c1;}
	node* rz() {return size=c[0]->size+c[1]->size+1,this;	}
}Tnull,*null=&Tnull;
node *last[2];
struct splay {
	node *root;
	splay() {
		root=(new node(*null))->rz();
		root->key=oo;
	}
	void zig(bool w) {
		last[w]=root;
		node *t=root->c[w];
		root->c[w]=null->c[w];
		null->c[w]=root;
		root=t;
	}
	void zigzig(bool w) {
		last[w]=root->c[w];
		node *t=root->c[w]->c[w];
		root->c[w]->c[w]=null->c[w];
		null->c[w]=root->c[w];
		root->c[w]=null->c[w]->c[!w];
		null->c[w]->c[!w]=root->rz();
		root=t;
	}
	void finish(bool w) {
		node *t=null->c[w],*p=root->c[!w];
		while (t!=null) {
			t=null->c[w]->c[w];
			null->c[w]->c[w]=p;
			p=null->c[w]->rz();
			null->c[w]=t;
		}
		root->c[!w]=p;
	}
	void select(int k) {
		int t;
		for (;;) {
			bool w=k>(t=root->c[0]->size);
			if (k==t|| root->c[w]==null) break;
			if (w) k-=t+1;
			bool ww=k>(t=root->c[w]->c[0]->size);
			if (k==t || root->c[w]->c[ww]==null) {zig(w);break;}
			if (ww) k-=t+1;
			w!=ww?zig(w),zig(ww):zigzig(w);
		}
		finish(0),finish(1);
		root->rz();
	}
	void search(int x) {
		for (;;) {
			bool w=x>root->key;
			if (root->c[w]==null) break;
			bool ww=x>root->c[w]->key;
			if (root->c[w]->c[ww]==null) {zig(w);break;}
			w!=ww?zig(w),zig(ww):zigzig(w);
		}
		finish(0); finish(1);
		root->rz();
		if (x>root->key) select(root->c[0]->size+1);
	}
	void ins(int x) {
		search(x);
		node *oldroot=root;
		root=new node(x,oldroot->c[0],oldroot);
		oldroot->c[0]=null;
		oldroot->rz();
		root->rz();
	}
	void del(int x) {
		search(x);
		node *oldroot=root;
		root=root->c[1];
		select(0);
		root->c[0]=oldroot->c[0];
		root->rz();
		delete oldroot;
	}
	int sel(int k) {return select(k-1),root->key;}
	int ran(int x) {return search(x),root->c[0]->size+1;}
};


最最后,orz ZKW.


阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/GE__he/article/details/52356474
文章标签: Splay
个人分类: 平衡树
想对作者说点什么? 我来说一句

zkw费用流

我要假期

SLYZ_wumingshi SLYZ_wumingshi

2017-04-29 07:56:13

阅读数:211

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭