Cod sursa(job #2658398)

Utilizator MarcGrecMarc Grec MarcGrec Data 13 octombrie 2020 21:01:17
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.13 kb
#include <vector>
#include <utility>
#include <cstdlib>
#include <exception>

template<typename T, typename TFunc>
class IntervalTree
{
private:
	struct Node
	{
		size_t a, b;

		Node *parent, *left, *right;

		T val;
	};

public:
	IntervalTree(const std::vector<T>* _cont, TFunc _functor) :
		functor(std::move(_functor)),
		initialCont(_cont),
		root(nullptr),
		leaves(_cont->size(), nullptr)
	{
		ConstructTree(0, _cont->size() - 1, &root);

		initialCont = nullptr;
	}

	~IntervalTree()
	{
		DestructDownwards(&root);
	}

	void UpdateValue(size_t index, const T& val)
	{
		leaves[index]->val = val;

		UpdateUpwards(leaves[index]);
	}

	T GetRange(size_t a, size_t b) const
	{
		return GetRange(leaves[a], a, b);
	}

private:
	void ConstructTree(const size_t a, const size_t b, Node** node)
	{
		if (a <= b)
		{
			(*node) = new Node;

			(*node)->parent = (*node)->right = (*node)->left = nullptr;

			(*node)->a = a;

			(*node)->b = b;

			if (a == b)
			{
				(*node)->val = initialCont->at(a);

				leaves[a] = (*node);
			}
			else
			{
				const size_t mean = (a + b) / 2;

				{
					Node* left;

					ConstructTree(a, mean, &left);
			
					(*node)->left = left;

					(*node)->left->parent = (*node);
				}

				{
					Node* right;

					ConstructTree(mean + 1, b, &right);

					(*node)->right = right;

					(*node)->right->parent = (*node);
				}

				UpdateNodeValue(*node);
			}
		}
		else
		{
			(*node) = nullptr;
		}
	}

	void DestructDownwards(Node** node)
	{
		if ((*node) != nullptr)
		{
			DestructDownwards(&((*node)->left));

			DestructDownwards(&((*node)->right));

			delete (*node);

			(*node) = nullptr;
		}
	}

	void UpdateNodeValue(Node* node)
	{
		if (node != nullptr)
		{
			if ((node->left != nullptr) && (node->right != nullptr))
			{
				node->val = functor(node->left->val, node->right->val);
			}
			else
			{
				if ((node->left != nullptr) && (node->right == nullptr))
				{
					node->val = node->left->val;
				}
				else
				{
					if ((node->left == nullptr) && (node->right != nullptr))
					{
						node->val = node->right->val;
					}
				}
			}
		}
	}

	void UpdateUpwards(Node* node)
	{
		if (node != nullptr)
		{
			UpdateNodeValue(node);
			UpdateUpwards(node->parent);
		}
	}

	T GetRange(Node* node, size_t a, size_t b) const
	{
		if (node->b < b)
		{
			T* ptrRightVal = nullptr;

			if (((node->parent->left == node) && (node->a != a)) || (node->a < a))
			{
				if (node->right->a >= a)
				{
					ptrRightVal = &(node->right->val);
				}
			}

			if (ptrRightVal != nullptr)
			{
				return functor(*ptrRightVal, GetRange(node->parent, a, b));
			}
			else
			{
				return GetRange(node->parent, a, b);
			}
		}
		else
		{
			if (node->b == b)
			{
				if (node->a >= a)
				{
					return node->val;
				}
				else
				{
					return GetRange(node->right, a, b);
				}
			}
			else
			{
				if (node->left->b >= b)
				{
					return GetRange(node->left, a, b);
				}
				else
				{
					if (node->left->a >= a)
					{
						return functor(node->left->val, GetRange(node->right, a, b));
					}
					else
					{
						return GetRange(node->right, a, b);
					}
				}
			}
		}
	}

private:
	TFunc functor;

private:
	const std::vector<T>* initialCont;

private:
	Node* root;

	std::vector<Node*> leaves;
};

#include <fstream>
#include <vector>
using namespace std;

ifstream fin("arbint.in");
ofstream fout("arbint.out");

int main()
{
	size_t n, m;
	
	fin >> n >> m;
	
	vector<int> initialVals(n);
	
	for (size_t i = 0; i < n; ++i)
	{
		fin >> initialVals[i];
	}
	
	IntervalTree<int, int(*)(int, int)> it(&initialVals, [] (int a, int b) { return (a > b) ? a : b; });
	
	for (size_t i = 0; i < m; ++i)
	{
		int c;
		
		fin >> c;
		
		if (c == 0)
		{
			size_t a, b;
			
			fin >> a >> b;
			
			fout << it.GetRange(a - 1, b - 1) << '\n';
		}
		else
		{
			size_t a;
			
			fin >> a;
			
			int b;
			
			fin >> b;
			
			it.UpdateValue(a - 1, b);
		}
	}
	
	fin.close();
	fout.close();
	return 0;
}