Cod sursa(job #198414)

Utilizator wefgefAndrei Grigorean wefgef Data 11 iulie 2008 13:09:23
Problema Arbori indexati binar Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 1.81 kb
#include <fstream>
#include <vector>

using namespace std;

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

class aib {
	int n;						// size of the aib
	vector<int> v;				// the actual aib

	int range_query(int);
public:
	aib(int);
	aib(const vector<int> &);
	void init(const vector<int> &);

	void update(int, int);
	int query1(int, int);
	int query2(int);
};

inline aib::aib(int size = 0) {
	n = size;
	v.resize(n);
}

inline aib::aib(const vector<int> &a) {
	init(a);
}

void aib::init(const vector<int> &a) {
	n = int(a.size());
	v.resize(n);

	for (int i = 1; i <= n; ++i) {
		v[i-1] += a[i-1];
		if (i + (i & (i ^ (i-1))) <= n)
			v[i + (i & (i ^ (i-1))) - 1] += v[i-1];
	}
}

void aib::update(int pos, int val) {
	while (pos <= n) {
		v[pos-1] += val;
		pos += pos & (pos ^ (pos-1));
	}
}

int aib::range_query(int pos) {
	int sum = 0;
	while (pos) {
		sum += v[pos-1];
		pos -= pos & (pos ^ (pos-1));
	}
	return sum;
}

int aib::query1(int a, int b) {
	return range_query(b) - range_query(a-1);
}

int aib::query2(int sum) {
	if (sum == 0) return -1;

	int pow = 1;
	while ((pow << 1) <= n)
		pow <<= 1;

	int pos = 0;
	while (pow) {
		if (pos + pow <= n && v[pos + pow - 1] <= sum) {
			sum -= v[pos + pow - 1];
			pos += pow;
		}
		pow >>= 1;
	}

	return sum ? -1 : pos;
}

int main() {
	int n, m;
	fin >> n >> m;

	vector<int> v;
	for (int i = 0; i < n; ++i) {
		int val;
		fin >> val;
		v.push_back(val);
	}

	aib A(v);

	for (int i = 0; i < m; ++i) {
		int op;
		fin >> op;

		if (op == 0) {
			int a, b;
			fin >> a >> b;
			A.update(a, b);
		}
		else if (op == 1) {
			int a, b;
			fin >> a >> b;
			fout << A.query1(a, b) << '\n';
		}
		else if (op == 2) {
			int a;
			fin >> a;
			fout << A.query2(a) << '\n';
		}
	}
}