Cod sursa(job #2658025)

Utilizator MarcGrecMarc Grec MarcGrec Data 12 octombrie 2020 22:30:53
Problema Arbori de intervale Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.18 kb
#include <vector>
#include <utility>
#include <cstdlib>

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]);
	}

	void GetRange(size_t a, size_t b, T** out)
	{
		if ((a <= b) && (b < leaves.size()))
		{
			(*out) = new T(GetRange(leaves[a], a, b));
		}
		else
		{
			(*out) = nullptr;
		}
	}

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)[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)
	{
		if (node->b < b)
		{
			T* ptrMyVal = nullptr;

			if (node->parent->right == node)
			{
				if ((node->a >= a) && (node->b <= b))
				{
					ptrMyVal = &(node->val);
				}
			}

			if (ptrMyVal != nullptr)
			{
				return functor(*ptrMyVal, GetRange(node->parent, a, b));
			}
			else
			{
				if (node->parent->b > b)
				{
					if ((node->a >= a) && (node->b <= b))
					{
						ptrMyVal = &(node->val);
					}
				}

				if (ptrMyVal != nullptr)
				{
					return functor(*ptrMyVal, 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
			{
				return GetRange(node->left, 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()
{
	int n, m;
	vector<int> V;
	
	fin >> n >> m;
	
	for (int i = 0; i < n; ++i)
	{
		int x;
		
		fin >> x;
		
		V.push_back(x);
	}
	
	IntervalTree<int, int(*)(int, int)>* it = new IntervalTree<int, int(*)(int, int)>(V, [](int a, int b) { return (a > b) ? a : b; });
	
	for (int i = 0; i < m; ++i)
	{
		int c, a, b;
		
		fin >> c >> a >> b;
		
		if (c == 0)
		{
			int* res;
			
			it->GetRange(a - 1, b - 1, &res);
			
			fout << (*res) << '\n';
			
			delete res;
		}
		else
		{
			it->UpdateValue(a - 1, b);
		}
	}
	
	delete it;
	
	fin.close();
	fout.close();
	return 0;
}