Cod sursa(job #454151)

Utilizator jeanFMI - Petcu Ion Cristian jean Data 11 mai 2010 19:18:30
Problema Zeap Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 5.58 kb
#include<stdio.h>
#include<stdlib.h>
#define Min(a,b) a<b ? a : b
#define Inf 1<<30
#define Black 0
#define Red 1

int i,N,nr,ok;
char op[4];

struct RBT 
{
	int key,color,dif_min;
	RBT *parent, *left, *right;
	RBT() {}
	RBT(int key, int color, int dif_min, RBT *parent, RBT *left, RBT *right)
	{
		this->key=key;
		this->color=color;
		this->dif_min=dif_min;
		this->parent=parent;
		this->left=left;
		this->right=right;
	}
} *Root, *NIL;

RBT* Minim(RBT *x)
{
	while(x->left!=NIL)
		x=x->left;
	
	return x;
}

RBT* Maxim(RBT *x)
{
	while(x->right!=NIL)
		x=x->right;
	
	return x;
}

void update(RBT *nod)
{
	int a, b;
	if(nod!=NIL)
	{
		a = Min( nod->right->dif_min, nod->left->dif_min ) ;
		b = Min( abs(nod->key-nod->right->key), abs(nod->key-nod->left->key) );
		nod->dif_min = Min(a,b);
	}
}

int find(RBT *x, int key)
{
	if(x==NIL) return 0;
	if(x->key==key) return 1;
	
	if(key < x->key) return find(x->left,key);
	return find(x->right,key);
}


void rotleft(RBT *n)
{
	RBT *t=n->right;
	
	n->right=t->left;
	
	if(t->left!=NIL) t->left->parent=n;
	
	t->parent=n->parent;
	if(t->parent==NIL) Root=t;
	else
		if( n == n->parent->left)
			n->parent->left=t;
		else
			n->parent->right=t;
	
	t->left=n;	
	n->parent=t;

	update(n);
	update(t);
}

void rotright(RBT *n)
{
	RBT *t=n->left;
	
	n->left=t->right;
	
	if(t->right!=NIL) t->right->parent=n;
	
	t->parent=n->parent;
	if(t->parent==NIL) Root=t;
	else
		if( n == n->parent->left)
			n->parent->left=t;
		else
			n->parent->right=t;
	
	t->right=n;	
	n->parent=t;

	update(n);
	update(t);
}

void InsertFix(RBT *x)
{
	if( x==Root || x->parent->color==Black )
	{
		Root->color=Black;
		return ;
	}
	
	if( x->parent == x->parent->parent->left)
	{
		RBT *y = x->parent->parent->right;
		
		if( y->color == Red )
		{
			x->parent->color=Black;
			y->color=Black;
			x->parent->parent->color=Black;
			InsertFix(x->parent->parent);
		}
		else
		{
			if( x == x->parent->right)
			{
				x=x->parent;
				rotleft(x);
			}
			
			x->parent->color=Black;
			x->parent->parent->color=Red;
			rotright(x->parent->parent);
		}
	}
	else
	{
		RBT *y = x->parent->parent->left;
		
		if( y->color == Red )
		{
			x->parent->color=Black;
			y->color=Black;
			x->parent->parent->color=Black;
			InsertFix(x->parent->parent);
		}
		else
		{
			if( x == x->parent->left)
			{
				x=x->parent;
				rotright(x);
			}
			
			x->parent->color=Black;
			x->parent->parent->color=Red;
			rotleft(x->parent->parent);
		}
	}	
}

void Insert(RBT *&n, RBT *p, int key)
{
	if( Root == NIL )
	{
		Root = new RBT(key,Black,Inf,NIL,NIL,NIL);
		N++;
		return ;
	}
	
	if( n == NIL )
	{
		n = new RBT(key,Red,Inf,p,NIL,NIL);
		N++;
		InsertFix(n);
		return;
	}
	
	if( key < n->key ) Insert(n->left,n,key);
	else 			   Insert(n->right,n,key);
}	

void EraseFix(RBT *x)
{
	if( x == Root || x->color == Red )
	{
		x->color=Black;
		return ;
	}
	
	if( x==x->parent->left )
	{
		RBT *w = x->parent->right;
		
		if( w->color == Red )
		{
			w->color=Black;
			x->parent->color=Red;
			rotleft(x->parent);
			w=x->parent->right;
		}
		
		if( w->left->color == Black && w->right->color == Black )
		{
			w->color=Red;
			EraseFix(x->parent);
		}
		else
		{
			if( w->right->color == Black )
			{
				w->left->color=Black;
				w->color=Red;
				rotright(w);
				w=x->parent->right;
			}
			w->color=x->parent->color;
			x->parent->color=Black;
			w->right->color=Black;
			rotleft(x->parent);
			EraseFix(Root);
		}
	}
	else
	{
		RBT *w = x->parent->left;
		
		if( w->color == Red )
		{
			w->color=Black;
			x->parent->color=Red;
			rotright(x->parent);
			w=x->parent->left;
		}
		
		if( w->left->color == Black && w->right->color == Black )
		{
			w->color=Red;
			EraseFix(x->parent);
		}
		else
		{
			if( w->left->color == Black )
			{
				w->right->color=Black;
				w->color=Red;
				rotleft(w);
				w=x->parent->left;
			}
			w->color=x->parent->color;
			x->parent->color=Black;
			w->left->color=Black;
			rotright(x->parent);
			EraseFix(Root);
		}
	}
}

void Erase( RBT *&n, int key )
{
	if( n == NIL )
	{
		ok=0;
		return;
	}
	
	if( n->key == key )
	{
		RBT *x, *y ,*z=n;
		
		if( z->left == NIL && z->right == NIL ) y=z;
		else
			if( z->right == NIL ) y=n->left;
		else 
			y=Minim(z->right);
		
		if( y->left != NIL ) x=y->left;
		else x=y->right;
		
		z->key=y->key;
		
		x->parent=y->parent;
		if( x->parent == NIL )
			Root=x;
		else
			if( y == y->parent->left)
				y->parent->left=x;
			else
				y->parent->right=x;
		
		int col = y->color;
		
		update(z);
		update(z->parent);
		update(x);
		update(x->parent);
		
		N--; 
		delete y;
		y=NIL;
		
		if( col == Black )
			EraseFix(x);
	}
	else
		if( key < n->key ) Erase(n->left,key);
	else
		Erase(n->right,key);
}


int main()
{
	freopen("zeap.in","r",stdin);
	freopen("zeap.out","w",stdout);
	
	NIL = Root = new RBT(-Inf,0,Inf,NULL,NULL,NULL);

	while( !feof(stdin) )
	{
		scanf("%s",op);
		
		if(op[0]=='I')
		{
			scanf("%d",&nr);
			Insert(Root,Root,nr);
		}
		else if(op[0]=='S')
		{
			scanf("%d",&nr);
			ok=1;
			Erase(Root,nr);
			if(!ok) printf("-1\n");
		}
		else if(op[0]=='C')
		{
			scanf("%d",&nr);
			printf("%d\n",find(Root,nr));
		}
		else if(op[1]=='I')
		{
			if(N<2) printf("-1\n");
			else
			printf("%d\n",Root->dif_min);
		}
		else
		{
			if(N<2) printf("-1\n");
			else
			printf("%d\n",Maxim(Root)->key-Minim(Root)->key);
		}
	}
	
	return 0;
}