[Tyvj1728]普通平衡树 解题报告

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



你可能感兴趣的:(平衡树)