package data_structures.trees;

public class FenwickTree { // one-based DS

	int n;
	int[] ft;
	
	FenwickTree(int size) { n = size; ft = new int[n+1]; }
	
	int rsq(int b) //O(log n)
	{
		int sum = 0;
		while(b > 0) { sum += ft[b]; b -= b & -b;}		//min?
		return sum;
	}
	
	int rsq(int a, int b) { return rsq(b) - rsq(a-1); }	
	
	void point_update(int k, int val)	//O(log n), update = increment
	{
		while(k <= n) { ft[k] += val; k += k & -k; }		//min?
	}

	int point_query(int idx)	// c * O(log n), c < 1
	{
		int sum = ft[idx];
		if(idx > 0)
		{
			int z = idx ^ (idx & -idx);
			--idx;
			while(idx != z)
			{
				sum -= ft[idx];
				idx ^= idx & -idx;
			}
		}
		return sum;
	}
	
	void scale(int c) {	for(int i = 1; i <= n; ++i)	ft[i] *= c;	}
	
	int findIndex(int cumFreq)
	{
		int msk = n;
		while((msk & (msk - 1)) != 0)
				msk ^= msk & -msk;			//msk will contain the MSB of n
		
		int idx = 0;
		while(msk != 0)
		{
			int tIdx = idx + msk;
			if(tIdx <= n && cumFreq >= ft[tIdx])
			{
				idx = tIdx;
				cumFreq -= ft[tIdx];
			}
			msk >>= 1;
		}
		if(cumFreq != 0)
			return -1;
		return idx;
	}
}