Cod sursa(job #295095)

Utilizator Omega91Nicodei Eduard Omega91 Data 2 aprilie 2009 23:23:39
Problema Arbori indexati binar Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 1.89 kb
#include <cstdio>

// NOTE: we use an imaginary array 'el', to reference actual values.
// Thus, for example, tree[12] = tree[10] + tree[11] + el[12];
// and tree[10] = tree[9] + el[10]; ( because tree[2k + 1] = el[2k + 1] )
template<class treeT>
class BinaryIndexedTree {
	treeT *tree;
	int N;
	treeT fixed_sum(int pos); // return el[1]+...+el[pos]
	public:
		BinaryIndexedTree(int n)
		{
			tree = new treeT [n];
			N = n;
		};
		void add(int pos, treeT S); // adds a number S to el[pos]
		treeT sum(int pos1, int pos2);  // sum of el in interval [a,b]
		int q2(treeT X); // return k such that el[1]+...+el[k] = X

};

template<class treeT>
treeT BinaryIndexedTree<treeT>::fixed_sum(int pos)
{
	treeT sum = 0;
	while(pos) {
		sum += tree[pos];
		pos = (pos - 1) & pos;
	}
	return sum;
}

template<class treeT>
void BinaryIndexedTree<treeT>::add(int pos, treeT S)
{
	while (pos <= N) {
		tree[pos] += S;
		pos += -pos & pos;
	}
}

template<class treeT>
treeT BinaryIndexedTree<treeT>::sum(int pos1, int pos2)
{
	return fixed_sum(pos2) - fixed_sum(pos1 - 1);
}

template<class treeT>
int BinaryIndexedTree<treeT>::q2(treeT X)
{
	int step, i;
	// we do a horny (sorry, I like calling interesting code snippets "sexy") BS:
	for (step = 1; step <= N; step <<= 1);
	for (i = 0; step; step >>= 1) {
		if (i + step <= N)
			if (fixed_sum(i + step) <= X) i += step;
	}
	if (fixed_sum(i) != X) return -1;
	else return i;
}

int main()
{
	int N, M, i, v1, v2, t;
	unsigned int elem;
	freopen("aib.in", "r", stdin);
	freopen("aib.out", "w", stdout);
	scanf("%d %d\n", &N, &M);
	BinaryIndexedTree<unsigned int> aib(N);
	for (i = 1; i <= N; ++i) {
		scanf("%d ", &elem);
		aib.add(i, elem);
	}
	for (i = 0; i != M; ++i) {
		scanf("%d ", &t);
		if (t == 2) {
			scanf("%d\n", &elem);
			printf("%d\n", aib.q2(elem));
		} else {
			scanf("%d %d\n", &v1, &v2);
			if (!t) aib.add(v1, v2);
			else printf("%d\n", aib.sum(v1, v2));
		}
	}
	return 0;
}