Cod sursa(job #1256935)

Utilizator fhandreiAndrei Hareza fhandrei Data 7 noiembrie 2014 00:23:18
Problema Hashuri Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 6.36 kb
// FMI - Grupa 135 - Semigrupa 2 - Hareza Andrei
// Include
#include <fstream>
using namespace std;
 
// Clase
template<class T> class AVL;

//#define NTH_ELEMENT
template<class U> class AVLNode
{
private:
	U value;
	AVLNode *leftSon, *rightSon, *father;
	int height;
	#ifdef NTH_ELEMENT
	int subtreeNum;
	#endif
	
	AVLNode()
	{
		value = 0;
		leftSon = rightSon = '\0';
		height = 0;
		#ifdef NTH_ELEMENT
		subtreeNum = 1;
		#endif
	}
	
	int balanceFactor()
	{
		return (leftSon? leftSon->height : -1) - (rightSon? rightSon->height : -1);
	}
	
	void resetHeight()
	{
		if(!leftSon && !rightSon)
		{
			height = 0;
			#ifdef NTH_ELEMENT
			subtreeNum = 1;
			#endif
		}
		else if(!leftSon)
		{
			height = rightSon->height + 1;
			#ifdef NTH_ELEMENT
			subtreeNum = rightSon->subtreeNum + 1;
			#endif
		}
		else if(!rightSon)
		{
			height = leftSon->height + 1;
			#ifdef NTH_ELEMENT
			subtreeNum = leftSon->subtreeNum + 1;
			#endif
		}
		else
		{
			height = max(leftSon->height, rightSon->height) + 1;
			#ifdef NTH_ELEMENT
			subtreeNum = leftSon->subtreeNum + rightSon->subtreeNum + 1;
			#endif
		}
		
		if(balanceFactor() == -2)
		{
			if(rightSon && rightSon->balanceFactor() == 1)
				rightSon->rightRotate();
			this->leftRotate();
		}
		
		if(balanceFactor() == 2)
		{
			if(leftSon && leftSon->balanceFactor() == -1)
				leftSon->leftRotate();
			this->rightRotate();
		}
	}
	
	void insert(U value)
	{
		if(value <= this->value)
		{
			if(this->leftSon)
				this->leftSon->insert(value);
			else
			{
				this->leftSon = new AVLNode;
				this->leftSon->value = value;
				this->leftSon->father = this;
			}
		}
		else
		{
			if(this->rightSon)
				this->rightSon->insert(value);
			else
			{
				this->rightSon = new AVLNode;
				this->rightSon->value = value;
				this->rightSon->father = this;
			}
		}
		resetHeight();
	}
	
	void printSorted(ostream &file)
	{
		if(this->leftSon)
			this->leftSon->printSorted(file);
		file << this->value << ' ';
		if(this->rightSon)
			this->rightSon->printSorted(file);
	}
	
	void leftRotate()
	{
		AVLNode *node = this->rightSon;
		
		if(this->isLeftSon())
			this->father->leftSon = node;
		else
			this->father->rightSon = node;
		node->father = this->father;
		
		this->rightSon = node->leftSon;
		if(this->rightSon)
			this->rightSon->father = this;
		
		node->leftSon = this;
		this->father = node;
		
		this->resetHeight();
		node->resetHeight();
	}
	
	void rightRotate()
	{
		AVLNode *node = this->leftSon;
		
		if(this->isLeftSon())
			this->father->leftSon = node;
		else
			this->father->rightSon = node;
		node->father = this->father;
		
		this->leftSon = node->rightSon;
		if(this->leftSon)
			this->leftSon->father = this;
		
		node->rightSon = this;
		this->father = node;
		
		this->resetHeight();
		node->resetHeight();
	}
	
	bool isLeftSon()
	{
		return this == this->father->leftSon;
	}
	
	bool query(U value)
	{
		if(this->value == value)
			return true;
		if(value < this->value)
		{
			if(!this->leftSon)
				return false;
			return this->leftSon->query(value);
		}
		else
		{
			if(!this->rightSon)
				return false;
			return this->rightSon->query(value);
		}
	}
	
	bool checkErase(U value)
	{
		if(this->value == value)
		{
			this->erase();
			return true;
		}
		if(value < this->value)
		{
			if(!this->leftSon)
				return false;
			
			if(this->leftSon->checkErase(value))
			{
				this->resetHeight();
				return true;
			}
			return false;
		}
		else
		{
			if(!this->rightSon)
				return false;
			
			if(this->rightSon->checkErase(value))
			{
				this->resetHeight();
				return true;
			}
			return false;
		}
	}
	
	void erase()
	{
		if(this->isLeaf())
		{
			if(this->isLeftSon())
				this->father->leftSon = '\0';
			else
				this->father->rightSon = '\0';
			
			delete this;
			return;
		}
		
		if(!this->rightSon)
		{
			swap(this->value, this->leftSon->value);
			this->leftSon->erase();
			this->resetHeight();
			return;
		}
		
		if(!this->leftSon)
		{
			swap(this->value, this->rightSon->value);
			this->rightSon->erase();
			this->resetHeight();
			return;
		}
		
		AVLNode *next = this->rightSon;
		while(next->leftSon)
			next=next->leftSon;
		
		swap(this->value, next->value);
		AVLNode *temp = next->father;
		next->erase();
		while(temp != this)
		{
			temp->resetHeight();
			temp = temp->father;
		}
		this->resetHeight();
	}
	
	bool isLeaf()
	{
		return !this->leftSon && !this->rightSon;
	}
	
	#ifdef NTH_ELEMENT
	int nthElement(int pos)
	{
		int leftNum = (leftSon? leftSon->subtreeNum : 0);
		if(leftNum+1 == pos)
			return this->value;
		if(pos <= leftNum)
			return leftSon->nthElement(pos);
		return rightSon->nthElement(pos-leftNum-1);
	}
	#endif
	
	template<class T> friend class AVL;
};

template<class T> class AVL
{
private:
	AVLNode<T> *abstractRoot;
	int size;
public:
	AVL()
	{
		abstractRoot = new AVLNode<T>;
		size = 0;
	}
	void insert(T value)
	{
		if(!size++)
		{
			abstractRoot->leftSon = new AVLNode<T>;
			abstractRoot->leftSon->father = abstractRoot;
			abstractRoot->leftSon->value = value;
		}
		else
			abstractRoot->leftSon->insert(value);
	}
	
	bool query(T value)
	{
		if(!size)
			return false;
		return abstractRoot->leftSon->query(value);
	}
	
	bool erase(T value)
	{
		if(!size)
			return false;
		
		if(abstractRoot->leftSon->checkErase(value))
		{
			--size;
			return true;
		}
		return false;
	}
	
	void printSorted(ostream &file)
	{
		if(!size)
			return;
		
		abstractRoot->leftSon->printSorted(file);
		file << '\n';
	}
	
	int getSize()
	{
		return size;
	}
	
	#ifdef NTH_ELEMENT
	int nthElement(int pos)
	{
		if(!size)
			return -1;
		return abstractRoot->leftSon->nthElement(pos);
	}
	#endif
	
};
 
// Variabile
ifstream in("hashuri.in");
ofstream out("hashuri.out");
 
int num;
int type, val;
AVL<int> tree;
 
// Main
int main()
{
    in >> num;
    while(num--)
    {
        in >> type >> val;
        if(type == 1)
        {
            if(!tree.query(val))
                tree.insert(val);
        }
        else if(type == 2)
            tree.erase(val);
        else
            out << (tree.query(val)? 1 : 0) << '\n';
    }
     
    in.close();
    out.close();
    return 0;
}