A quick guide to Binary Indexed Tree or Fenwick Tree

A quick guide to Binary Indexed Tree or Fenwick Tree
A quick guide to Binary Indexed Tree or Fenwick Tree

A Binary Indexed Tree (BIT), conjointly cited as a Fenwick Tree could also be an arrangement accustomed with efficiency calculate and update additive frequency tables, or prefix sums.

BITs usually solely show up in Gold issues, but they could begin showing a lot of typing in Silver. the matter area unit typically outlined as follows: Given Associate in Nursing array A of size N and some associative operation + that is not essentially addition (although we’ll assume it’s throughout the lecture for the sake of simplicity), we might wish to support the next two operations:

  • Query(i): running total of all the frequency from zero to i in f (f[0] + [1] + f[2] + … + f[i])
  • Update(i, x): add x to f[i]

The naive solutions to the current drawback have time complexness O(N) for question and O(1) for an update or the opposite method around. Higher solutions use knowledge structures, like section trees or BITs, that a lot of equally balance the time complexness between the two totally different operations and support each in O(log N).

An additive frequency array permits us to calculate the add of the vary of values in O(1), as long as there don’t seem to be any changes to the information once the queries begin.

But contemplate things wherever we’d amendment the value at Associate in Nursing index in Associate in Nursing array, then question for the addition of a range of values at intervals the array, followed by some a lot of changes and a lot of queries. throughout this sort of scenario, an additive frequency array would still provide US O(1) question times.

However, it would take O(n) time to update when every change (Basically, if we tend to modify one index throughout an additive frequency array, all different indexes on top of it would have to be compelled to have this worth accessorial to that conjointly). Here could also be a fast illustration: Current additive frequency array:

Now, contemplate adding the value 2 to the information, recalling that index i stores the number of values however or equal to i. The adjusted array is: 

We had to edit each index 2 or greater, which might take O(n) for a cumulative frequency array of size n.

Thus, we might sort of a replacement arrangement wherever each the question and thus the update area unit comparatively quick. The inventive insight here is that maybe if we tend to store knowledge throughout a distinct method, maybe we’ll cut back the update time by quite bit whereas acquisition solely a modest increase in question time. It achieves a O(lg n) time for each the update and thus the question.

A Fenwick tree is often enforced as Associate in Nursing array (a std::vector throughout this blog), wherever indices fall at intervals the vary [ one … n ] . we’ll create the vector huge enough to contain all the weather and conjointly skip index zero for simplicity. Let’s assume that the Fenwick tree is linear unit. Then the part at index i is to blame for components at intervals the vary [ i − L S O n e ( i ) + one … i ], that is from the index: i ablated by its least important one-bit and one, to the index: i

Operations: Once the tree is created, the latter question is that thanks to using it, dynamically. There area unit 2 basic operations: one. query, 2. update. we’ll endure them in details.

blog banner 1

Query: The primary common operation is to question frequency from the start(1) to some index b . Namely, we tend to decision all question r s Q . So the subsequent is however we tend to do {a Question|an issue|a matter} r s q ( b ):

  • (Init Sum) Let s u m ← zero
  • (Accumulate Sum) s u m ← s u m + f t [ b ]
  • (Get new b ) b ← b − L S O n e ( b )
  • (If ended?) If b == zero, come s u m, otherwise, goto step two

With the on top of question offered, getting the additive frequency between 2 indices [ a … b ] wherever a ! = one is simple, simply judge r s q ( a, b ) = r s Q ( b ) − r s Q ( a − one ).

Update (Adjust value): Let’s name the operation of change the price of the part at index k by altering its value by v to be adjusted ( k, v ), this is typically done by the next steps:

  • (Adjust worth at index k ) f t [ k ] + = v
  • (Get new k ) k ← k + L S O n e ( k )
  • (If ended?) If k < f t . s i z e ( ) , goto step one

Index throughout an additive frequency array, array[i] stores ∑ 𝑥[𝑘] 𝑖 𝑘=0, wherever x[k] represents the primary things. throughout a binary index tree (which is essentially simply keep in Associate in Nursing array), every index can store an add of values from the primary array conjointly, however, the set of values summed at every index area unit progressing to be a lot of sophisticated than throughout an additive frequency array.

Number of Values summed at index i: The value keeps in index I of a binary index tree is based upon the binary illustration of I, thus the name, binary index tree. For this description, let x[i] represent the primary values. every index can perpetually store an add of a gaggle of values of x[i] that options a size that is a perfect power of 2. especially, the number of values accessorial to urge the value keep in index i is 2L, wherever L represents the place of all-time low one bit. as an example, if the binary illustration of i is 10000100, then there area unit twenty-two = four values summed at index I, since the littlest quantity important bit equal to one is at intervals {the two|the two} 2 place, third from the right. If i in binary is 1010100000, then the corresponding worth is that the add of 25 values at intervals the first array.

Which values are summed at index i: Now that we tend to all understand what proportion values of the first array area unit summed at index i, we tend to should specify that values comprised that add.
The values that consist of the add at index i area unit the last two L values of x[i].

Thus, we tend to finally will write this mathematically:

BIT[i] = ∑ 𝑥[𝑘] 𝑖 𝑘=𝑖−2 𝐿+1 , wherever L is that all-time low one-bit location as antecedently outlined. Here may even be a table of what’s keep at intervals the first sixteen indexes of a binary index tree:

Indexes to vary for an Update: Consider Associate in a Nursing update to Associate in Nursing arbitrary index x[i] of the first array. If you examine the table on top of, we’ll see that the total range of indexes that raise x[i] is an index at intervals the scale of the total table. contemplate x[5] – it’s a vicinity of BIT[5], BIT[6], BIT[8] and BIT[16]. to urge from five to six, we add 1, the worth of rock bottom one bit in five. to urge from vi to eight, we add 2, the worth of rock bottom one bit in vi. to urge from eight to sixteen, we add 8, the worth of rock bottom one little bit of eight, then forth.

Thus, the algorithmic program for adding D to the worth of x[i] is as follows:

  • Let curIndex = i.
  • whereas curIndex < sizeof(BIT)
    2a. BIT[curIndex] += D
    2b. curIndex += valueOfLowestOneBit(curIndex)

Indexes to feature for a matter: Consider simply supporting queries at intervals the vary one to i. (Any vary question area unit typically delineated as a result of the distinction of 2 vary queries of currently .) Let’s contemplate summing the values x[1] + x[2] +… + x[13]. 1st we’d add BIT[13]. This simply adds x[13]. Then we’d add BIT[12], adding x[9] + x[10] + x[11] + x[12]. Finally we’d add BIT[8], that may add x[1]+x[2]+x[3]+x[4]+x[5]+x[6]+x[7]+x[8].

In short, we tend to add our current index we tend to area unit at at intervals the BIT array, then compute the worth of rock bottom one bit from this index. Thus, the operating algorithmic program for the question add of x[1] to x[i] is as follows: one. Let curIndex = i.

  • Let add = zero.
  • whereas curIndex > zero
    2a. add += BIT[curIndex]
    2b. curIndex -= valueOfLowestOneBit(curIndex)

Implementation:

#define FENWICK_TREE

#define FENWICK_TREE

#include

// Least Significant One-bit Macro

define LSOne(i) (i & (-i))

class FenwickTree{
private:
std::vector ft;
public:
FenwickTree(int n){ ft.assign(n+1, 0); }

// function to question range [1, b]
int rsq(int b){
int sum = 0;
for(; b; b -= LSOne(b)){
sum += ft[b];
}
return sum;
}

// function to question range [a, b]
int rsq(int a, int b){
return rsq(b) – (a == 1 ? 0 : rsq(a-1));
}

// modifies value of the k-th element by v
void adjust(int k, int v){
for( ; k < (int)ft.size(); k += LSOne(k)){
ft[k] += v;
}
}
};

Let’s try to understand a very popular problem in Fenwick tree. Problem Statement: Some of the more elite (and not-so-elite) coders around participate during a certain unnamed programming contest. In the said contest, there are multiple sorts of competitions. Here, we consider the Open and highschool competition types. for every type, each competitor receives a rating, an integer between 1 and 100000, inclusive. A coder’s rating is predicated upon his or her level of performance in matches and is calculated employing a complicated formula which, thankfully, you’ll not be asked to implement.


Although the Open and highschool ratings for a coder who has participated in both competition types lately are usually close, this is often not always the case. especially, highschool matches are more about speed, since many coders are ready to solve all the issues, whereas Open matches require more thinking and there’s a steeper curve in terms of problem difficulty.

Problem Statement
You are given N coders (1 ≤ N ≤ 300000), conveniently numbered from 1 to N. Each of those coders participates in both highschool and Open matches. for every coder, you’re also given an Open rating Ai and a highschool rating Hi. Coder i is claimed to be better than coder j if and as long as both of coder i’s ratings are greater than or adequate to coder j’s corresponding ratings, with a minimum of one being greater. for every coder i, determine what percentage coders coder i is best than.

Input Format
On the primary line of input may be a single integer N, as described above. N lines then follow. Line i+1 contains two space-separated integers, Ai and Hi.
Output Format
Line i should contain the number of coders that coder i is best than.

Sample Input
8
1798 1832
862 700
1075 1089
1568 1557
2575 1984
1033 950
1656 1649
1014 1473
Sample Output
6
0
2
4
7
1
5
1

Solution:

include<bits/stdc++.h>

#define mod 1000000007

#define inf 1000000000000

#define root2 1.41421

#define root3 1.73205

#define pi 3.14159

#define MAX 100100

#define ll long long int

#define PII pair

#define f first

#define s second

#define ss(n) scanf(“%lld”, &n)

#define ssf(n) scanf(“%lf”, &n)

#define mk make_pair

#define PLL pair

#define gc getchar

#define pb push_back

#define FR(i, a, b) for(ll i=(ll)a;i<=(ll)b;i++)

#define RFR(i, a, b) for(ll i=(ll)a;i>=(ll)b;i–)

using namespace std;

struct Rating {
ll A, H, index;
};
bool compare(Rating a, Rating b) {
if(a.A!=b.A)
return a.AMAX]; ll ans[3MAX]; ll get_count(ll idx) { ll sum=0; while(idx>0) {
sum+=BIT[idx];
idx-=idx&(-idx);
}
return sum;
}
ll updateBIT(ll idx, ll val) {
while(idx<MAX) {
BIT[idx]+=val;
idx+=idx&(-idx);
}
}

int main() {
ll i, c;
ss(n);
memset(BIT, 0, sizeof BIT);
FR(i, 0, n-1) {
ss(R[i].A);
ss(R[i].H); R[i].index=i;
}
sort(R, R+n, compare);
FR(i, 0, n-1) {
c=1;
while((i<n-1)&&(R[i].A==R[i+1].A)&&(R[i].H==R[i+1].H)) {
ans[R[i].index]=get_count(R[i].H);
i++;
c++;
}
ans[R[i].index]=get_count(R[i].H);
updateBIT(R[i].H, c);
}
FR(i, 0, n-1)
cout<<ans[i]<<endl;
}

For more such problems please visit Codezen by Coding Ninjas.

By Yogesh Kumar