zkw Splay学习笔记

来源:互联网 发布:用c语言求以内素数 编辑:程序博客网 时间:2024/06/05 11:07

最近。。

最近心里颇不平静。

最近花了三天时间学了zkw Splay,发现这玩意儿真TM难写;加上各种Code Trick也还是写了好久,还有各种错误,一直在炸。

一些心得:

①维护size时不需要考虑太多东西,只需要改变孩子指针后直接用孩子的size维护即可,注意要在两个地方维护:

旋转的时候维护;

翻转子树链表的时候维护。

②zkw Splay中左临时树是一些没有右孩子子树的节点,然后。。为了方便(真的方便么。。),我们可以一开始用每棵子树的右儿子存储它的父节点,然后再把根表反转。

反转真是一件蛋疼的事,注意到新根也还是有左右子树的,所以其实就相当于从一个根表的表头加入另一个根表的表头。(!!这玩意儿我想了好久才想明白,真是坑爹。)

③Select中向下探测两层真的是一件很蛋疼的事,我是通过人工让两层不一样以解决在下一层取到所需节点的问题的。

④最重要的:一定要时刻注意变量的意义!它改变了没有?它现在是什么!尤其是在坑爹的表头插入和维护的时候。。经常弄错导致炸飞。

⑤zkw。。真是太牛了!我感觉我现在的代码能力还不太能驾驭得了zkw Splay。。以后如果没有被卡就还是都老老实实写普通Splay吧。。

代码(模板题-普通平衡树):

#include<iostream>using namespace std;#include<cstdio>#include<cstring>#include<algorithm>struct SS{SS * c[2];int key,num,size;}* null=new SS((SS){null,null,0,0,0}),* root=new SS((SS){null,null,0x7fffffff,1,1}),* newroot=new SS((SS){null,null,0,0,0});inline void mtn(){SS * now,* next;for(int D=0;D<2;++D)for(now=newroot->c[D];now!=null;now=next){next=now->c[D];now->c[D]=root->c[!D];root->c[!D]=now;now->size=now->c[0]->size+now->c[1]->size+now->num;}root->size=root->c[0]->size+root->c[1]->size+root->num;newroot->c[0]=null;newroot->c[1]=null;}inline void search(int A){bool D;SS * tmp;while(root->key!=A){D=root->key<A;if(root==null){root=new SS((SS){null,null,A,0,0});break;}if(root->c[D]!=null&&root->c[D]->key!=A&&D==(root->c[D]->key<A)){tmp=root->c[D];root->c[D]=tmp->c[!D];tmp->c[!D]=root;root->size=root->c[0]->size+root->c[1]->size+root->num;root=tmp;}if(root==null){root=new SS((SS){null,null,A,0,0});break;}tmp=root->c[D];root->c[D]=newroot->c[D];newroot->c[D]=root;root=tmp;}mtn();}inline void select(int A){bool D,d;SS * tmp;while(1){D=root->size-root->c[1]->size<A;if(!D&&root->c[0]->size<A)break;if(D)A-=root->size-root->c[1]->size;if(root->c[D]->c[0]->size<A&&root->c[D]->size-root->c[D]->c[1]->size>=A)d=!D;else d=root->c[D]->size-root->c[D]->c[1]->size<A;if(D==d){if(d)A-=root->c[1]->size-root->c[1]->c[1]->size;tmp=root->c[D];root->c[D]=tmp->c[!D];tmp->c[!D]=root;root->size=root->c[0]->size+root->c[1]->size+root->num;root=tmp;}tmp=root->c[D];root->c[D]=newroot->c[D];newroot->c[D]=root;root=tmp;}mtn();}char * ptr=(char *)malloc(2000000);inline void in(int &x){bool flag=0;while(*ptr<'0'||*ptr>'9')if(*ptr++=='-')flag=1;x=0;while(*ptr>47&&*ptr<58)x=x*10+*ptr++-'0';if(flag)x=-x;}int main(){freopen("phs.in","r",stdin);freopen("phs.out","w",stdout);fread(ptr,1,2000000,stdin);int N,ans,opt,x;in(N);SS * tmp;while(N--){in(opt),in(x);switch(opt){case 1:search(x);++root->num;++root->size;break;case 2:search(x);if(!--root->num){tmp=root;root=root->c[1];select(1);root->c[0]=tmp->c[0];root->size+=root->c[0]->size;delete tmp;}else --root->size;break;case 3:search(x);printf("%d\n",root->c[0]->size+1);break;case 4:select(x);printf("%d\n",root->key);break;case 5:ans=-0x7fffffff;tmp=root;while(tmp!=null)if(tmp->key>=x)tmp=tmp->c[0];else{ans=max(tmp->key,ans);tmp=tmp->c[1];}printf("%d\n",ans);break;case 6:ans=0x7fffffff;tmp=root;while(tmp!=null)if(tmp->key<=x)tmp=tmp->c[1];else{ans=min(tmp->key,ans);tmp=tmp->c[0];}printf("%d\n",ans);}}}


0 0