Cod sursa(job #2986383)

Utilizator the_horoHorodniceanu Andrei the_horo Data 28 februarie 2023 15:01:55
Problema Arbori indexati binar Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 1.99 kb
#include <array>
#include <cassert>
#include <fstream>
#include <iostream>
#include <utility>
#include <vector>


namespace aib {
	namespace {
		std::vector<int> m_storage;
	}

	void add (int poz, int amount) {
		for (; poz < m_storage.size(); poz += poz & (-poz))
			m_storage[poz] += amount;
	}

	int query (int up_to_poz) {
		int result = 0;

		for (int poz = up_to_poz; poz > 0; poz -= poz & (-poz))
			result += m_storage[poz];

		return result;
	}

	int query (int left, int right) {
		return query(right) - query(left - 1);
	}

	void init (int size) {
		m_storage.resize(size + 1, 0);
	}

	std::pair<int, int> under_upper (const int target) {
		int poz = 0, sum = 0;
		// arbitrary big enough power of 2, do `log2` for more precision
		for (int i = 1 << 30; i; i >>= 1) {
			const int pretender = poz | i;

			if (pretender < m_storage.size() && sum + m_storage[pretender] <= target) {
				sum += m_storage[pretender];
				poz = pretender;
			}
		}

		return {sum, poz};
	}

	void debug () {
		std::clog << "The vector has " << m_storage.size() << " elements:" << std::endl;
		for (auto val: m_storage)
			std::clog << val << ' ';
		std::clog << std::endl;
	}
}


int main () {
	std::ifstream in("aib.in");
	in.exceptions(in.failbit);
	std::ofstream out("aib.out");
	out.exceptions(out.failbit);

	int n, q;
	in >> n >> q;

	aib::init(n);

	for (int i = 1; i <= n; ++ i) {
		int number;
		in >> number;

		aib::add(i, number);
		/* aib::debug(); */
	}

	/*
	aib::debug();
	for (int i = 1; i <= n; ++ i)
		std::clog << "query(" << i << ") returned: " << aib::query(i) << std::endl;
	*/

	for (int i = 0; i < q; ++ i) {
		int t;
		in >> t;

		switch (t) {
		case 0: {
			int x, y;
			in >> x >> y;

			aib::add(x, y);
			break;
		} case 1: { 
			int a, b;
			in >> a >> b;

			out << aib::query(a, b) << '\n';
			break;
		} case 2: {
			int sum;
			in >> sum;
			
			auto [got, poz] = aib::under_upper(sum);

			if (got == sum)
				out << poz << '\n';
			else
				out << "-1\n";
			break;
		} default:
			assert(false);
		}
	}
}