Cod sursa(job #1764876)

Utilizator andreioneaAndrei Onea andreionea Data 26 septembrie 2016 01:20:36
Problema Arbori de intervale Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 2.72 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <utility>
#include <memory>
#include <iterator>

namespace cpp14
{
	template <class T, class... Args>
	std::unique_ptr<T> make_unique(Args&&... args) {return std::unique_ptr<T>(new T(std::forward<Args>(args)...));}
};

struct file_manip {

	std::ifstream fin;
	std::ofstream fout;

	file_manip(const char* filename) {
		std::string infilename  = std::string(filename) + ".in";
		std::string outfilename = std::string(filename) + ".out";
		fin.open(infilename.c_str());
		fout.open(outfilename.c_str());
	}

	template <class T>
	file_manip& operator << (const T& rhs) {
		fout << rhs;
		return *this;
	}
	template <class T>
	file_manip& operator >> (T& rhs) {
		fin >> rhs;
		return *this;
	}

	template <class T>
	std::ostream_iterator<T> GetOstreamIterator() {
		return std::ostream_iterator<T>(fout);
	} 

	template <class T>
	std::istream_iterator<T> GetIstreamIterator() {
		return std::istream_iterator<T>(fin);
	}

	template <class T>
	std::vector<T> ReadVector(int size)
	{
		std::vector<T> v;
		v.reserve(size);
		std::copy_n(GetIstreamIterator<int>(), size, std::back_inserter(v));
		return v;
	}
};

struct Arbint
{
	std::unique_ptr<Arbint> left_child, right_child;
	unsigned int value : 30;
	int left : 17;
	int right : 17;

	Arbint(int left, int right, const std::vector<unsigned int>& vals) : left(left), right(right)
	{
		if (left == right)
		{
			value = vals[left];
		}
		else
		{
			auto middle = (left + right) / 2;
			left_child = cpp14::make_unique<Arbint>(left, middle, vals);
			right_child = cpp14::make_unique<Arbint>(middle + 1, right, vals);
			value = std::max(left_child->value, right_child->value);
		}
	}
	Arbint(const std::vector<unsigned int>& vals)
		: Arbint(0, vals.size() - 1, vals) {}

	void Update(unsigned int newVal, int pos)
	{
		if (left == right)
		{
			value = newVal;
		}
		else
		{
			const auto middle = (left + right) / 2;
			if (pos <= middle)
			{
				left_child->Update(newVal, pos);
			}
			else
			{
				right_child->Update(newVal, pos);
			}
			value = std::max(left_child->value, right_child->value);
		}
	}

	unsigned int GetValue(int a, int b) const
	{
		if (left >= a && right <= b)
			return value;
		const auto middle = (left + right) / 2;
		auto v1 = 0u;
		auto v2 = 0u;
		if (middle >= a)
		{
			v1 = left_child->GetValue(a, b);
		}
		if (middle < b)
		{
			v2 = right_child->GetValue(a, b);
		}
		return std::max(v1, v2);
	}

};

int main(int argc, char const *argv[])
{
	file_manip fm("arbint");
	int N, M;
	int op;
	unsigned int a, b;
	fm >> N >> M;
	Arbint arb(fm.ReadVector<unsigned int>(N));
	while (M--)
	{
		fm >> op >> a >> b;
		if (op == 0)
		{
			fm << arb.GetValue(a - 1, b - 1) << "\n";
		}
		else
		{
			arb.Update(b, a - 1);
		}
	}
	return 0;
}