用这道题学了一下Splay,结果在删除的时候遇到问题。
我删除节点的方法是把待删除节点splay到根上,然后把它的后继splay到根的右儿子上,然后将其左儿子接到右儿子上——结果!就在这里!犯了一个错误,我只维护了右儿子的左儿子指针,却忘了维护左儿子的父指针!
这加上前几天做的派遣。。应该说都深深地锻炼了我指针的维护能力;什么时候该维护,一定要想明白。
#include<iostream> using namespace std; #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> struct SS{ SS * f,* c[2]; int key,num,size; bool is_root; }* nil=new SS((SS){0,0,0,0,0,0,0}),* Stmp=new SS((SS){nil,nil,nil,0x7fffffff,1,1,1}),* root=Stmp; inline void zig(SS * x,bool D){ SS * ftr=x->f; x->f=ftr->f; if(ftr->is_root){ x->is_root=1; ftr->is_root=0; } if(x->f->c[0]==ftr)x->f->c[0]=x; else x->f->c[1]=x; ftr->c[D]=x->c[!D]; ftr->c[D]->f=ftr; ftr->f=x; x->c[!D]=ftr; ftr->size=ftr->c[0]->size+ftr->c[1]->size+ftr->num; x->size=x->c[0]->size+x->num+x->c[1]->size; } inline void splay(SS * x){ bool D; while(!x->is_root){ D=x->f->c[1]==x; if(!x->f->is_root&&D==(x->f->f->c[1]==x->f))zig(x->f,D); zig(x,D); } root=x; } int ans; inline void succ(SS * x,int A){ if(x->key<=A){ if(x->c[1]!=nil) succ(x->c[1],A); } else{ ans=min(x->key,ans); if(x->c[0]!=nil) succ(x->c[0],A); } } inline void pred(SS * x,int A){ //cout<<"P:("<<x->key<<","<<A<<")"<<" "<<(x->c[0]!=nil?x->c[0]->key:0)<<" "<<(x->c[1]!=nil?x->c[1]->key:0)<<"\n"; if(x->key>=A){ if(x->c[0]!=nil) pred(x->c[0],A); } else{ ans=max(x->key,ans); if(x->c[1]!=nil) pred(x->c[1],A); } } inline SS * insert(SS * x,int A){ if(x->key==A)return x; if(x->key<A) if(x->c[1]!=nil) return insert(x->c[1],A); else return x->c[1]=new SS((SS){x,nil,nil,A,0,0,0}); if(x->c[0]!=nil) return insert(x->c[0],A); else return x->c[0]=new SS((SS){x,nil,nil,A,0,0,0}); } inline SS * find(SS * x,int A){ if(x->key==A)return x; if(x->key<A)return find(x->c[1],A); return find(x->c[0],A); } inline SS * query(SS * x,int A){ //cout<<"Q("<<A<<"):"<<x->key<<" "<<x->c[0]->size<<" "<<x->num<<endl; if(x->c[0]->size>=A)return query(x->c[0],A); if(x->size-x->c[1]->size>=A)return x; return query(x->c[1],A-x->num-x->c[0]->size); } char * ptr=(char *)malloc(10000000); 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; } inline void Prt(SS * x){ if(x->c[0]!=nil)Prt(x->c[0]); printf("%d ",x->key); if(x->c[1]!=nil)Prt(x->c[1]); } int main(){ SS * succnode; nil->f=nil; nil->c[0]=nil; nil->c[1]=nil; fread(ptr,1,10000000,stdin); int N,opt,x; in(N); while(N--){ in(opt),in(x); switch(opt){ case 1: splay(insert(root,x)); ++root->num; ++root->size; break; case 2: splay(find(root,x)); if(!(--root->num)){ root->c[1]->is_root=1; succnode=root->c[1]; while(succnode->c[0]!=nil)succnode=succnode->c[0]; splay(succnode); root->c[0]=root->f->c[0]; root->size+=root->f->c[0]->size; root->c[0]->f=root; delete root->f; root->f=nil; } else --root->size; break; case 3: splay(find(root,x)); printf("%d\n",root->c[0]->size+1); break; case 4: splay(query(root,x)); printf("%d\n",root->key); break; case 5: ans=-0x7fffffff; pred(root,x); printf("%d\n",ans); break; default: ans=0x7fffffff; succ(root,x); printf("%d\n",ans); break; }/* Prt(root); printf("\n");*/ } }