Cod sursa(job #2898045)

Utilizator widzAndrei-Daniel Tava widz Data 5 mai 2022 19:46:18
Problema Zeap Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.69 kb
#include <fstream>
#include <iostream>
#include <string>
using namespace std;

class Zeap
{
	struct node
	{
		int data;
		node* left, * right;
		node* parent;
		node(int x, node* parent) : data(x), left(), right(), parent(parent) {}
		~node()
		{
			delete left;
			delete right;
		}
	};

	node* root;
	size_t size;
	int max,min,p_elem,s_elem;

	node* predecessor(node* crt_node)
	{
		if (crt_node->data == min)
			return nullptr;
		if (crt_node->left != nullptr)
		{
			crt_node = crt_node->left;
			while (crt_node->right != nullptr)
				crt_node = crt_node->right;
		}
		else
		{
			node* src_node = crt_node;
			crt_node = crt_node->parent;
			while (crt_node->data >= src_node->data)
				crt_node = crt_node->parent;
		}

		return crt_node;
	}
	node* successor(node* crt_node)
	{
		if (crt_node->data == max)
			return nullptr;
		if (crt_node->right != nullptr)
		{
			crt_node = crt_node->right;
			while (crt_node->left != nullptr)
				crt_node = crt_node->left;
		}
		else
		{
			node* src_node = crt_node;
			crt_node = crt_node->parent;
			while (crt_node->data > src_node->data)
				crt_node = crt_node->parent;
		}
		return crt_node;
	}
	void restructureMin()
	{
		if (size < 2)
			return;
		int min_dif = -1;
		node* crt_node = nodeSearch(min);
		node* succ = successor(crt_node);
		while (succ != nullptr)
		{
			int dif = abs(succ->data - crt_node->data);
			if (dif < min_dif || min_dif == -1)
			{
				min_dif = dif;
				s_elem = succ->data;
				p_elem = crt_node->data;
			}
			crt_node = succ;
			succ = successor(crt_node);
		}
	}

	node* nodeSearch(const int& x) const
	{
		node* crt_node = root;
		if (crt_node == nullptr)
			return nullptr;
		while (crt_node->data != x)
		{

			if (crt_node->data < x)
				if (crt_node->right != nullptr)
					crt_node = crt_node->right;
				else
					return crt_node;
			else
			{
				if (crt_node->left != nullptr)
					crt_node = crt_node->left;
				else
					return crt_node;
			}

		}
		return crt_node;
	}
	static void removeFromParent(node* crt_node)
	{
		node* par = crt_node->parent;
		if (par != nullptr)
		{
			if (par->left == crt_node)
				par->left = nullptr;
			else
				par->right = nullptr;
		}
	}


public:
	Zeap() : root(), max(), min(), p_elem(), s_elem(), size(0) {}
	int maxDif() const
	{
		if (size > 1)
			return abs(max - min);
		else
			return -1;
	}
	int minDif() const
	{
		if (size > 1)
			return abs(s_elem - p_elem);
		else
			return -1;
	}

	bool search(const int& x) const
	{
		if (nodeSearch(x)->data == x)
			return true;
		else
			return false;
	}

	void insert(const int& x)
	{

		node* crt_node = nodeSearch(x);
		if (crt_node == nullptr || crt_node->data != x)
		{
			++size;
			if (crt_node == nullptr)
			{
				root = new node(x, nullptr);
				p_elem = max = min = root->data;
				
			}
			else
			{

				if (crt_node->data < x)
					crt_node = crt_node->right = new node(x, crt_node);
				else
					crt_node = crt_node->left = new node(x, crt_node);

				if (crt_node->data > max)
					max = crt_node->data;
				if (crt_node->data < min)
					min = crt_node->data;
				if (size == 2)
				{
					if (crt_node->data > root->data)
					{
						s_elem = crt_node->data;
						p_elem = root->data;
					}
					else
					{
						s_elem = root->data;
						p_elem = crt_node->data;
					}
				}
				else
				{
					node* pred = predecessor(crt_node);
					node* succ = successor(crt_node);
					int min_dif = minDif();
					if (pred != nullptr && abs(crt_node->data - pred->data) < min_dif)
					{
						s_elem = crt_node->data;
						p_elem = pred->data;
					}
					if (succ != nullptr && abs(crt_node->data - succ->data) < min_dif)
					{
						s_elem = succ->data;
						p_elem = crt_node->data;
					}
				}
			}
		}
	}

	int remove(const int& x)
	{
		node* crt_node = nodeSearch(x);
		if (crt_node->data != x)
			return -1;
		else
		{
			--size;
			bool restructure = false;
			const int data = crt_node->data;
			if (crt_node->data == max)
			{
				max = predecessor(crt_node)->data;
			}
			if (crt_node->data == min)
			{
				min = successor(crt_node)->data;
			}
			if (crt_node->data == p_elem || crt_node->data == s_elem)
				restructure = true;
			if (crt_node->left == nullptr && crt_node->right == nullptr)
			{
				removeFromParent(crt_node);
				delete crt_node;
			}
			else
			{
				node* rep = predecessor(crt_node);
				if (crt_node->left == nullptr)
				{
					rep = successor(crt_node);
					crt_node->data = rep->data;
					node* rep_it = rep;
					while (rep_it->right != nullptr)
						rep_it = rep_it->right;         //o sa fie amuzant sa descifrez asta
					rep_it->right = crt_node->right;    // mai tarziu, dar sunt prea obosit
					crt_node->right->parent = rep_it;   // sa mai documentez
					crt_node->right = rep->right;
					removeFromParent(rep);
					rep->right = nullptr;
					delete rep;

				}
				else
				{
					crt_node->data = rep->data;
					node* rep_it = rep;
					while (rep_it->left != nullptr)
						rep_it = rep_it->left;         //o sa fie amuzant sa descifrez asta
					rep_it->left = crt_node->left;    // mai tarziu, dar sunt prea obosit
					crt_node->left->parent = rep_it;   // sa mai documentez
					crt_node->left = rep->left;
					removeFromParent(rep);
					rep->right = nullptr;
					delete rep;
				}
				if (restructure)
					restructureMin();
			}
			return data;


		}

	}

};

enum class commands
{
	ins,
	rem,
	src,
	max,
	min
};

void resolveCommand(const string& input, commands& cmd, int& par)
{
	switch (input[0])
	{
	case 'I':
	{
		cmd = commands::ins;
		par = stoi(&input[2]);
		return;
	}
	case 'S':
	{
		cmd = commands::rem;
		par = stoi(&input[2]);
		return;
	}
	case 'C':
	{
		cmd = commands::src;
		par = stoi(&input[2]);
		return;
	}
	case 'M':
	{
		if (input[1] == 'I')
		{
			cmd = commands::min;
			return;
		}
		else
		{
			cmd = commands::max;
			return;
		}
	}
	}
}

int main()
{

	ifstream in("zeap.in");
	ofstream out("zeap.out");
	Zeap my_zeap;
	string input;
	commands cmd;
	int param;
	while (getline(in, input))
	{
		resolveCommand(input, cmd, param);
		switch (cmd)
		{
		case commands::ins:
		{
			my_zeap.insert(param);
			break;
		}
		case commands::rem:
		{
			int res = my_zeap.remove(param);
			if (res == -1)
				out << "-1\n";
			break;
		}
		case commands::src:
		{
			out << my_zeap.search(param) << "\n";
			break;
		}
		case commands::min:
		{
			out << my_zeap.minDif() << "\n";
			break;
		}
		case commands::max:
		{
			out << my_zeap.maxDif() << "\n";
			break;
		}
		}
	}
	return 0;
}