Binary Indexed Tree: Range Update and Range Queries in C++

C++Server Side ProgrammingProgramming

Here, we are given an array of size n which initially has all elements 0. And there are some queries that are to be performed on it. There are two types of queries −

• update(l,r, value) − Add value to the elements of the array that are between index l to r. For example, update(2, 4, 5) will update the array by placing the element 2 at the element at index 4 and 5.

• getRangeSum(l, r) − Find the sum of elements within the range of elements from l to r. For example, getRangeSum(4, 7) will find the sum of all elements with index 4, 5, 6, 7.

Let’s take an example to understand the problem,

Input

n = 7 , arr[7] = {0,0,0,0,0,0,0}
Q1 = update(3, 6, 4)
Q2 = update(0, 4, 2)
Q3 = Sum(2, 5)

Output

10

Explanation

Solving queries: Q1 - update(3, 6, 4) = {0, 0, 0, 4, 4, 4, 4}
Q2 - update(0, 4, 2) = {2, 2, 2, 2, 2, 4, 4}
Q3 - sum(2, 5) = 2+2+2+4 = 10

To solve this problem a naive approach will be to update the array at each update query and then find the sum but this is not so effective so let’s learn a more effective approach to solving the problem.

Let’s see the effect of the update queries on the sum query. Sum query is of the form sum[l,r], we will split this into sum queries of form sum[0,k] and then subtract the sum to the lower limit from the sum to lower limit.

sum[l,r] = sum[0,r] - sum[0,l]

So, the effects of the sum[0,k] will be reflected on the sum[l,r]. The sum variable k will lie in 3 different regions based on its relative value and will range [l,r] of the update query.

Region 1 − k lies between o and l i.e. 0 < k < l

In this case, the update query will not affect the sum query.

Region 2 − k lies between l and r i.e. l ≤ k ≤ r

In this case, the sum query will entertain values from l to k.

Region 3 − k is greater than r i.e. k>r

In this case, the sum query will entertain all values between l to r.

Now, let’s see the program to solve the Range Update and Range Queries

//Program to solve the Range Update and Range Queries

Example

Live Demo

#include <bits/stdc++.h>
using namespace std;
int getSum(int BITree[], int i){
int sum = 0;
i++;
while (i>0) {
sum += BITree[i];
i -= i & (-i);
}
return sum;
}
void updateBITree(int BITree[], int n, int i, int val) {
i = i + 1;
while (i <= n) {
BITree[i] += val;
i += i & (-i);
}
}
void update(int BITTree1[], int BITTree2[], int n, int l, int r, int value) {
updateBITree(BITTree1,n,l,value);
updateBITree(BITTree1,n,r+1,-value);
updateBITree(BITTree2,n,l,value*(l-1));
updateBITree(BITTree2,n,r+1,-value*r);
}
int sum(int x, int BITTree1[], int BITTree2[]) {
return (getSum(BITTree1, x) * x) - getSum(BITTree2, x);
}
int getRangeSum(int l, int r, int BITTree1[], int BITTree2[]) {
return sum(r, BITTree1, BITTree2) - sum(l-1, BITTree1, BITTree2);
}
int *createBITree(int n) {
int *BITree = new int[n+1];
for (int i=1; i<=n; i++)
BITree[i] = 0;
return BITree;
}
int main(){
int n = 7;
int *BITTree1, *BITTree2;
BITTree1 = createBITree(n);
BITTree2 = createBITree(n);
update(BITTree1,BITTree2,n,3,6,9);
update(BITTree1,BITTree2,n, 0, 4, 5);
cout<<"The output of sum query after applying all update queries is \t"      <<getRangeSum(1,5,BITTree1,BITTree2);
return 0;
}

Output

The output of sum query after applying all update queries is
Published on 17-Jul-2020 12:07:52