最近。。
最近心里颇不平静。
最近花了三天时间学了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); } } }
原文地址:http://blog.csdn.net/ta201314/article/details/42650805