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