ZKW Splay

原创 2016年08月29日 20:58:18

来宣传我大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.


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

zkw Splay学习笔记

最近。。 最近心里颇不平静。 最近花了三天时间学了zkw Splay,发现这玩意儿真TM难写;加上各种Code Trick也还是写了好久,还有各种错误,一直在炸。 一些心得: ①维护size时不需...

【zkw线段树套自顶向下splay】cf44g

考场上队友写这道题tle了,貌似是数组寻址花的时间过久加上splay常数过大 因此赛后re一遍,很久没写数据结构,调了老半天,最后9000+ms过了,虽然写得有点冗而且还是没改成指针,但是zkw线段树...

费用流模板——ZKW

先让我们回顾一下SPFA算法:设d[x] = x到T的最短距离对于i,j必有d[j] + c[i][j] >= d[i]SPFA算法就是每次找到d[j] + c[i][j] = d[i]的等式,走最短...

ZKW线段树

zkw线段树

zkw线段树

zkw线段树

codevs1080 第一次用ZKW线段树

题目描述 Description一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间[a,b]中所有元素的和;修改的规则是指定某一个格子x,加上或者...
  • cww97
  • cww97
  • 2016年01月07日 11:17
  • 354

最小费用流的zkw算法

最小费用最大流ZKW算法

SPOJ 1716 GSS3 zkw线段树

这个线段树写起来还算简单和之前

poj 2195 Going Home【zkw费用流】

题目链接:http://poj.org/problem?id=2195题意:每个人都走到一个屋子的最小花费。二分图类型代码:#include #include #include #i...

从入门到精通: 最小费用流的“zkw算法”

点击打开链接 1. 网络流的一些基本概念 点击阅读   很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本的概念反而说不清楚. 虽然不同的模型在具体叫法上可能不相同, ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ZKW Splay
举报原因:
原因补充:

(最多只允许输入30个字)