Cod sursa(job #1764880)

Utilizator andreioneaAndrei Onea andreionea Data 26 septembrie 2016 03:13:07
Problema Arbori de intervale Scor 10
Compilator cpp Status done
Runda Arhiva educationala Marime 3.45 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <utility>
#include <memory>
#include <iterator>
#include <cmath>

namespace cpp14
{
	template <class T, class... Args>
	std::unique_ptr<T> make_unique(Args&&... args) noexcept {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(std::size_t size)
	{
		std::vector<T> v;
		v.reserve(size);
		std::copy_n(GetIstreamIterator<int>(), size, std::back_inserter(v));
		return v;
	}
};

struct Arbint
{
	std::vector<int32_t> heap_;
	int32_t N;

	Arbint(const std::vector<int32_t>& vals) : N(vals.size())
	{
		const auto totalSize = 1 + std::ceil(std::log(vals.size()) / log(2.0f));
		heap_.reserve(totalSize);
		std::fill_n(heap_.begin(), 5, 0);
		Initialise(0, N - 1, 0, vals);
	}

	void Initialise(int32_t left, int32_t right, int32_t idx, const std::vector<int32_t>& vals)
	{
		if (left == right)
		{
			heap_[idx] = vals[left];
		}
		else
		{
			const auto middle = (left + right) / 2;
			const auto left_child = idx * 2 + 1;
			const auto right_child = left_child + 1;
			Initialise(left, middle, left_child, vals);
			Initialise(middle + 1, right, right_child, vals);
			heap_[idx] = std::max(heap_[left_child], heap_[right_child]);
		}
	}

	void InsertAndUpdate(int32_t left, int32_t right, int32_t val, int32_t pos, int32_t idx = 0)
	{
		if (left == right)
		{
			heap_[idx] = val;
		}
		else
		{
			const auto middle = (left + right) / 2;
			const auto left_child = idx * 2 + 1;
			const auto right_child = left_child + 1;
			if (pos <= middle)
			{
				InsertAndUpdate(left, middle, val, pos, left_child);
			}
			else
			{
				InsertAndUpdate(middle + 1, right, val, pos, right_child);
			}
			heap_[idx] = std::max(heap_[left_child], heap_[right_child]);
		}
	}
	void Update(int32_t newVal, int32_t pos)
	{
		InsertAndUpdate(0, N - 1, newVal, pos);
	}

	int32_t GetValue(int32_t a, int32_t b, int32_t left = 0, int32_t right = -1, int32_t idx = 0) const
	{
		if (right == -1)
		{
			right = N - 1;
		}

		if (left >= a && right <= b)
			return heap_[idx];

		const auto middle = (left + right) / 2;
		const auto left_child = idx * 2 + 1;
		const auto right_child = left_child + 1;

		if (middle >= a && b > middle)
			return std::max(GetValue(a, b, left, middle, left_child), GetValue(a, b, middle + 1, right, right_child));

		if (middle >= a)
		{
			return GetValue(a, b, left, middle, left_child);
		}

		return GetValue(a, b, middle + 1, right, right_child);
	}

};

int main(int argc, char const *argv[])
{
	file_manip fm("arbint");
	std::size_t N, M;
	int op;
	int32_t a, b;
	fm >> N >> M;
	Arbint arb(fm.ReadVector<int32_t>(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;
}