用这道题学了一下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");*/
}
}