最近。。
最近心里颇不平静。
最近花了三天时间学了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);
}
}
}