Cod sursa(job #453644)

Utilizator jeanFMI - Petcu Ion Cristian jean Data 11 mai 2010 10:09:46
Problema Zeap Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 6.43 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 )
	{
		N--;
		RBT *y, *x;
		int col;
				
		if( n->left == NIL && n->right == NIL )
		{
			NIL->parent = n->parent;
			col=n->color;
			delete n; 
			n=NIL;
			update(NIL->parent);
			if(col==Black)
				EraseFix(NIL);
			return ;
		}
		else 
			if( n->right == NIL ) y=n->left;
		else
			y=Minim(n->right);
		
		x=y->right;
		col=y->color;
		
		if(y->parent==n)
		{
			if( y == n->left ) 
			{
				y->right = n->right;
				n->right->parent=y;
			}
			else
			{
				y->left = n->left;
				n->left->parent=y;
			}
			update(y);
			
			y->parent=n->parent;
			
			if(n->parent==NIL)
			{
				delete n;
				n=NIL;
				Root=y;
				return;
			}
			
			else
			{
				if(n==n->parent->left)
					n->parent->left=y;
				else
					n->parent->right=y;
				
				update(y->parent);
				delete n;
				n=NIL;
			}
			
			if(col==Black)
				EraseFix(x);
			return ;
		}
		
		x->parent=y->parent;
		if( y==y->parent->left)
			y->parent->left=x;
		else
			y->parent->right=x;
		
		update(x->parent);
		
		y->left = n->left;
		n->left->parent=y;
		y->right= n->right;
		n->left->parent=y;
		update(y);
		
		y->parent=n->parent;
		if(n->parent==NIL)
		{
			delete n;
			n=NIL;
			Root=y;
		}
		else
		{
			if(n = n->parent->left)
				n->parent->left=y;
			else 
				n->parent->right=y;
			delete n;
			n=NIL;
			update(y->parent);
		}
		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;
}