Related Articles
Two Dimensional Binary Indexed Tree or Fenwick Tree
• Difficulty Level : Hard
• Last Updated : 09 Dec, 2019

Prerequisite – Fenwick Tree

We know that to answer range sum queries on a 1-D array efficiently, binary indexed tree (or Fenwick Tree) is the best choice (even better than segment tree due to less memory requirements and a little faster than segment tree).

Can we answer sub-matrix sum queries efficiently using Binary Indexed Tree ?

The answer is yes. This is possible using a 2D BIT which is nothing but an array of 1D BIT.

Algorithm:

We consider the below example. Suppose we have to find the sum of all numbers inside the highlighted area- We assume the origin of the matrix at the bottom – O.Then a 2D BIT exploits the fact that-

```
Sum under the marked area = Sum(OB) - Sum(OD) -
Sum(OA) + Sum(OC) ``` In our program, we use the getSum(x, y) function which finds the sum of the matrix from (0, 0) to (x, y).
Hence the below formula :

```Sum under the marked area = Sum(OB) - Sum(OD) -
Sum(OA) + Sum(OC)

The above formula gets reduced to,

Query(x1,y1,x2,y2) = getSum(x2, y2) -
getSum(x2, y1-1) -
getSum(x1-1, y2) +
getSum(x1-1, y1-1) ```

where,
x1, y1 = x and y coordinates of C
x2, y2 = x and y coordinates of B

The updateBIT(x, y, val) function updates all the elements under the region – (x, y) to (N, M) where,
N = maximum X co-ordinate of the whole matrix.
M = maximum Y co-ordinate of the whole matrix.

The rest procedure is quite similar to that of 1D Binary Indexed Tree. Below is the C++ implementation of 2D indexed tree

## C++

 `/* C++ program to implement 2D Binary Indexed Tree`` ` `2D BIT is basically a BIT where each element is another BIT.``Updating by adding v on (x, y) means it's effect will be found``throughout the rectangle [(x, y), (max_x, max_y)],``and query for (x, y) gives you the result of the rectangle``[(0, 0), (x, y)], assuming the total rectangle is``[(0, 0), (max_x, max_y)]. So when you query and update on``this BIT,you have to be careful about how many times you are``subtracting a rectangle and adding it. Simple set union formula``works here.`` ` `So if you want to get the result of a specific rectangle``[(x1, y1), (x2, y2)], the following steps are necessary:`` ` `Query(x1,y1,x2,y2) = getSum(x2, y2)-getSum(x2, y1-1) -``                     ``getSum(x1-1, y2)+getSum(x1-1, y1-1)`` ` `Here 'Query(x1,y1,x2,y2)' means the sum of elements enclosed``in the rectangle with bottom-left corner's co-ordinates``(x1, y1) and top-right corner's co-ordinates - (x2, y2)`` ` `Constraints -> x1<=x2 and y1<=y2`` ` `    ``/\`` ``y  |``    ``|           --------(x2,y2)``    ``|          |       |``    ``|          |       |``    ``|          |       |``    ``|          ---------``    ``|       (x1,y1)``    ``|``    ``|___________________________``   ``(0, 0)                   x-->`` ` `In this program we have assumed a square matrix. The``program can be easily extended to a rectangular one. */`` ` `#include``using` `namespace` `std;`` ` `#define N 4 // N-->max_x and max_y`` ` `// A structure to hold the queries``struct` `Query``{``    ``int` `x1, y1; ``// x and y co-ordinates of bottom left``    ``int` `x2, y2; ``// x and y co-ordinates of top right``};`` ` `// A function to update the 2D BIT``void` `updateBIT(``int` `BIT[][N+1], ``int` `x, ``int` `y, ``int` `val)``{``    ``for` `(; x <= N; x += (x & -x))``    ``{``        ``// This loop update all the 1D BIT inside the``        ``// array of 1D BIT = BIT[x]``        ``for` `(; y <= N; y += (y & -y))``            ``BIT[x][y] += val;``    ``}``    ``return``;``}`` ` `// A function to get sum from (0, 0) to (x, y)``int` `getSum(``int` `BIT[][N+1], ``int` `x, ``int` `y)``{``    ``int` `sum = 0;`` ` `    ``for``(; x > 0; x -= x&-x)``    ``{``        ``// This loop sum through all the 1D BIT``        ``// inside the array of 1D BIT = BIT[x]``        ``for``(; y > 0; y -= y&-y)``        ``{``            ``sum += BIT[x][y];``        ``}``    ``}``    ``return` `sum;``}`` ` `// A function to create an auxiliary matrix``// from the given input matrix``void` `constructAux(``int` `mat[][N], ``int` `aux[][N+1])``{``    ``// Initialise Auxiliary array to 0``    ``for` `(``int` `i=0; i<=N; i++)``        ``for` `(``int` `j=0; j<=N; j++)``            ``aux[i][j] = 0;`` ` `    ``// Construct the Auxiliary Matrix``    ``for` `(``int` `j=1; j<=N; j++)``        ``for` `(``int` `i=1; i<=N; i++)``            ``aux[i][j] = mat[N-j][i-1];`` ` `    ``return``;``}`` ` `// A function to construct a 2D BIT``void` `construct2DBIT(``int` `mat[][N], ``int` `BIT[][N+1])``{``    ``// Create an auxiliary matrix``    ``int` `aux[N+1][N+1];``    ``constructAux(mat, aux);`` ` `    ``// Initialise the BIT to 0``    ``for` `(``int` `i=1; i<=N; i++)``        ``for` `(``int` `j=1; j<=N; j++)``            ``BIT[i][j] = 0;`` ` `    ``for` `(``int` `j=1; j<=N; j++)``    ``{``        ``for` `(``int` `i=1; i<=N; i++)``        ``{``            ``// Creating a 2D-BIT using update function``            ``// everytime we/ encounter a value in the``            ``// input 2D-array``            ``int` `v1 = getSum(BIT, i, j);``            ``int` `v2 = getSum(BIT, i, j-1);``            ``int` `v3 = getSum(BIT, i-1, j-1);``            ``int` `v4 = getSum(BIT, i-1, j);`` ` `            ``// Assigning a value to a particular element``            ``// of 2D BIT``            ``updateBIT(BIT, i, j, aux[i][j]-(v1-v2-v4+v3));``        ``}``    ``}`` ` `    ``return``;``}`` ` `// A function to answer the queries``void` `answerQueries(Query q[], ``int` `m, ``int` `BIT[][N+1])``{``    ``for` `(``int` `i=0; i     3 8 1`` ``1  |       4 6 7 5                                 6 7 5`` ``0  |       2 4 8 9``    ``|``  ``--|------ 0 1 2 3 ----> x``    ``|`` ` `    ``Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30`` ` `    ``*/`` ` `    ``Query q[] = {{1, 1, 3, 2}, {2, 3, 3, 3}, {1, 1, 1, 1}};``    ``int` `m = ``sizeof``(q)/``sizeof``(q);`` ` `    ``answerQueries(q, m, BIT);`` ` `    ``return``(0);``}`

## Java

 `/* Java program to implement 2D Binary Indexed Tree `` ` `2D BIT is basically a BIT where each element is another BIT. ``Updating by adding v on (x, y) means it's effect will be found ``throughout the rectangle [(x, y), (max_x, max_y)], ``and query for (x, y) gives you the result of the rectangle ``[(0, 0), (x, y)], assuming the total rectangle is ``[(0, 0), (max_x, max_y)]. So when you query and update on ``this BIT,you have to be careful about how many times you are ``subtracting a rectangle and adding it. Simple set union formula ``works here. `` ` `So if you want to get the result of a specific rectangle ``[(x1, y1), (x2, y2)], the following steps are necessary: `` ` `Query(x1,y1,x2,y2) = getSum(x2, y2)-getSum(x2, y1-1) - ``                    ``getSum(x1-1, y2)+getSum(x1-1, y1-1) `` ` `Here 'Query(x1,y1,x2,y2)' means the sum of elements enclosed ``in the rectangle with bottom-left corner's co-ordinates ``(x1, y1) and top-right corner's co-ordinates - (x2, y2) `` ` `Constraints -> x1<=x2 and y1<=y2 `` ` `    ``/\ ``y | ``    ``|     --------(x2,y2) ``    ``|     | | ``    ``|     | | ``    ``|     | | ``    ``|     --------- ``    ``| (x1,y1) ``    ``| ``    ``|___________________________ ``(0, 0)             x--> `` ` `In this program we have assumed a square matrix. The ``program can be easily extended to a rectangular one. */``class` `GFG``{ ``static` `final` `int` `N = ``4``; ``// N-.max_x and max_y `` ` `// A structure to hold the queries ``static` `class` `Query ``{ ``    ``int` `x1, y1; ``// x and y co-ordinates of bottom left ``    ``int` `x2, y2; ``// x and y co-ordinates of top right `` ` `        ``public` `Query(``int` `x1, ``int` `y1, ``int` `x2, ``int` `y2)``        ``{``            ``this``.x1 = x1;``            ``this``.y1 = y1;``            ``this``.x2 = x2;``            ``this``.y2 = y2;``        ``}``         ` `}; `` ` `// A function to update the 2D BIT ``static` `void` `updateBIT(``int` `BIT[][], ``int` `x,``                      ``int` `y, ``int` `val) ``{ ``    ``for` `(; x <= N; x += (x & -x)) ``    ``{ ``        ``// This loop update all the 1D BIT inside the ``        ``// array of 1D BIT = BIT[x] ``        ``for` `(; y <= N; y += (y & -y)) ``            ``BIT[x][y] += val; ``    ``} ``    ``return``; ``} `` ` `// A function to get sum from (0, 0) to (x, y) ``static` `int` `getSum(``int` `BIT[][], ``int` `x, ``int` `y) ``{ ``    ``int` `sum = ``0``; `` ` `    ``for``(; x > ``0``; x -= x&-x) ``    ``{ ``        ``// This loop sum through all the 1D BIT ``        ``// inside the array of 1D BIT = BIT[x] ``        ``for``(; y > ``0``; y -= y&-y) ``        ``{ ``            ``sum += BIT[x][y]; ``        ``} ``    ``} ``    ``return` `sum; ``} `` ` `// A function to create an auxiliary matrix ``// from the given input matrix ``static` `void` `constructAux(``int` `mat[][], ``int` `aux[][]) ``{ ``    ``// Initialise Auxiliary array to 0 ``    ``for` `(``int` `i = ``0``; i <= N; i++) ``        ``for` `(``int` `j = ``0``; j <= N; j++) ``            ``aux[i][j] = ``0``; `` ` `    ``// Conthe Auxiliary Matrix ``    ``for` `(``int` `j = ``1``; j <= N; j++) ``        ``for` `(``int` `i = ``1``; i <= N; i++) ``            ``aux[i][j] = mat[N - j][i - ``1``]; `` ` `    ``return``; ``} `` ` `// A function to cona 2D BIT ``static` `void` `construct2DBIT(``int` `mat[][],``                           ``int` `BIT[][]) ``{ ``    ``// Create an auxiliary matrix ``    ``int` `[][]aux = ``new` `int``[N + ``1``][N + ``1``]; ``    ``constructAux(mat, aux); `` ` `    ``// Initialise the BIT to 0 ``    ``for` `(``int` `i = ``1``; i <= N; i++) ``        ``for` `(``int` `j = ``1``; j <= N; j++) ``            ``BIT[i][j] = ``0``; `` ` `    ``for` `(``int` `j = ``1``; j <= N; j++) ``    ``{ ``        ``for` `(``int` `i = ``1``; i <= N; i++) ``        ``{ ``            ``// Creating a 2D-BIT using update function ``            ``// everytime we/ encounter a value in the ``            ``// input 2D-array ``            ``int` `v1 = getSum(BIT, i, j); ``            ``int` `v2 = getSum(BIT, i, j - ``1``); ``            ``int` `v3 = getSum(BIT, i - ``1``, j - ``1``); ``            ``int` `v4 = getSum(BIT, i - ``1``, j); `` ` `            ``// Assigning a value to a particular element ``            ``// of 2D BIT ``            ``updateBIT(BIT, i, j, aux[i][j] - ``                     ``(v1 - v2 - v4 + v3)); ``        ``} ``    ``} ``    ``return``; ``} `` ` `// A function to answer the queries ``static` `void` `answerQueries(Query q[], ``int` `m, ``int` `BIT[][]) ``{ ``    ``for` `(``int` `i = ``0``; i < m; i++) ``    ``{ ``        ``int` `x1 = q[i].x1 + ``1``; ``        ``int` `y1 = q[i].y1 + ``1``; ``        ``int` `x2 = q[i].x2 + ``1``; ``        ``int` `y2 = q[i].y2 + ``1``; `` ` `        ``int` `ans = getSum(BIT, x2, y2) -``                  ``getSum(BIT, x2, y1 - ``1``) - ``                  ``getSum(BIT, x1 - ``1``, y2) +``                  ``getSum(BIT, x1 - ``1``, y1 - ``1``); `` ` `        ``System.out.printf(``"Query(%d, %d, %d, %d) = %d\n"``, ``                ``q[i].x1, q[i].y1, q[i].x2, q[i].y2, ans); ``    ``} ``    ``return``; ``} `` ` `// Driver Code``public` `static` `void` `main(String[] args) ``{ ``    ``int` `mat[][] = { {``1``, ``2``, ``3``, ``4``}, ``                    ``{``5``, ``3``, ``8``, ``1``}, ``                    ``{``4``, ``6``, ``7``, ``5``}, ``                    ``{``2``, ``4``, ``8``, ``9``} }; `` ` `    ``// Create a 2D Binary Indexed Tree ``    ``int` `[][]BIT = ``new` `int``[N + ``1``][N + ``1``]; ``    ``construct2DBIT(mat, BIT); `` ` `    ``/* Queries of the form - x1, y1, x2, y2 ``    ``For example the query- {1, 1, 3, 2} means the sub-matrix- ``        ``y ``        ``/\ ``    ``3 | 1 2 3 4     Sub-matrix ``    ``2 | 5 3 8 1     {1,1,3,2} --.     3 8 1 ``    ``1 | 4 6 7 5                                 6 7 5 ``    ``0 | 2 4 8 9 ``        ``| ``    ``--|------ 0 1 2 3 ---. x ``        ``| ``     ` `        ``Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30 ``    ``*/``    ``Query q[] = {``new` `Query(``1``, ``1``, ``3``, ``2``), ``                 ``new` `Query(``2``, ``3``, ``3``, ``3``), ``                 ``new` `Query(``1``, ``1``, ``1``, ``1``)}; ``    ``int` `m = q.length; `` ` `    ``answerQueries(q, m, BIT); ``}``} `` ` `// This code is contributed by 29AjayKumar`

## C#

 `/* C# program to implement 2D Binary Indexed Tree `` ` `2D BIT is basically a BIT where each element is another BIT. ``Updating by.Adding v on (x, y) means it's effect will be found ``throughout the rectangle [(x, y), (max_x, max_y)], ``and query for (x, y) gives you the result of the rectangle ``[(0, 0), (x, y)], assuming the total rectangle is ``[(0, 0), (max_x, max_y)]. So when you query and update on ``this BIT,you have to be careful about how many times you are ``subtracting a rectangle and.Adding it. Simple set union formula ``works here. `` ` `So if you want to get the result of a specific rectangle ``[(x1, y1), (x2, y2)], the following steps are necessary: `` ` `Query(x1,y1,x2,y2) = getSum(x2, y2)-getSum(x2, y1-1) - ``                    ``getSum(x1-1, y2)+getSum(x1-1, y1-1) `` ` `Here 'Query(x1,y1,x2,y2)' means the sum of elements enclosed ``in the rectangle with bottom-left corner's co-ordinates ``(x1, y1) and top-right corner's co-ordinates - (x2, y2) `` ` `Constraints -> x1<=x2 and y1<=y2 `` ` `    ``/\ ``y | ``    ``|     --------(x2,y2) ``    ``|     | | ``    ``|     | | ``    ``|     | | ``    ``|     --------- ``    ``| (x1,y1) ``    ``| ``    ``|___________________________ ``(0, 0)             x--> `` ` `In this program we have assumed a square matrix. The ``program can be easily extended to a rectangular one. */``using` `System;`` ` `class` `GFG``{ ``static` `readonly` `int` `N = 4; ``// N-.max_x and max_y `` ` `// A structure to hold the queries ``public` `class` `Query ``{ ``    ``public` `int` `x1, y1; ``// x and y co-ordinates of bottom left ``    ``public` `int` `x2, y2; ``// x and y co-ordinates of top right `` ` `        ``public` `Query(``int` `x1, ``int` `y1, ``int` `x2, ``int` `y2)``        ``{``            ``this``.x1 = x1;``            ``this``.y1 = y1;``            ``this``.x2 = x2;``            ``this``.y2 = y2;``        ``}``         ` `}; `` ` `// A function to update the 2D BIT ``static` `void` `updateBIT(``int` `[,]BIT, ``int` `x,``                    ``int` `y, ``int` `val) ``{ ``    ``for` `(; x <= N; x += (x & -x)) ``    ``{ ``        ``// This loop update all the 1D BIT inside the ``        ``// array of 1D BIT = BIT[x] ``        ``for` `(; y <= N; y += (y & -y)) ``            ``BIT[x,y] += val; ``    ``} ``    ``return``; ``} `` ` `// A function to get sum from (0, 0) to (x, y) ``static` `int` `getSum(``int` `[,]BIT, ``int` `x, ``int` `y) ``{ ``    ``int` `sum = 0; `` ` `    ``for``(; x > 0; x -= x&-x) ``    ``{ ``        ``// This loop sum through all the 1D BIT ``        ``// inside the array of 1D BIT = BIT[x] ``        ``for``(; y > 0; y -= y&-y) ``        ``{ ``            ``sum += BIT[x, y]; ``        ``} ``    ``} ``    ``return` `sum; ``} `` ` `// A function to create an auxiliary matrix ``// from the given input matrix ``static` `void` `constructAux(``int` `[,]mat, ``int` `[,]aux) ``{ ``    ``// Initialise Auxiliary array to 0 ``    ``for` `(``int` `i = 0; i <= N; i++) ``        ``for` `(``int` `j = 0; j <= N; j++) ``            ``aux[i, j] = 0; `` ` `    ``// Conthe Auxiliary Matrix ``    ``for` `(``int` `j = 1; j <= N; j++) ``        ``for` `(``int` `i = 1; i <= N; i++) ``            ``aux[i, j] = mat[N - j, i - 1]; `` ` `    ``return``; ``} `` ` `// A function to cona 2D BIT ``static` `void` `construct2DBIT(``int` `[,]mat,``                        ``int` `[,]BIT) ``{ ``    ``// Create an auxiliary matrix ``    ``int` `[,]aux = ``new` `int``[N + 1, N + 1]; ``    ``constructAux(mat, aux); `` ` `    ``// Initialise the BIT to 0 ``    ``for` `(``int` `i = 1; i <= N; i++) ``        ``for` `(``int` `j = 1; j <= N; j++) ``            ``BIT[i, j] = 0; `` ` `    ``for` `(``int` `j = 1; j <= N; j++) ``    ``{ ``        ``for` `(``int` `i = 1; i <= N; i++) ``        ``{ ``            ``// Creating a 2D-BIT using update function ``            ``// everytime we/ encounter a value in the ``            ``// input 2D-array ``            ``int` `v1 = getSum(BIT, i, j); ``            ``int` `v2 = getSum(BIT, i, j - 1); ``            ``int` `v3 = getSum(BIT, i - 1, j - 1); ``            ``int` `v4 = getSum(BIT, i - 1, j); `` ` `            ``// Assigning a value to a particular element ``            ``// of 2D BIT ``            ``updateBIT(BIT, i, j, aux[i,j] - ``                    ``(v1 - v2 - v4 + v3)); ``        ``} ``    ``} ``    ``return``; ``} `` ` `// A function to answer the queries ``static` `void` `answerQueries(Query []q, ``int` `m, ``int` `[,]BIT) ``{ ``    ``for` `(``int` `i = 0; i < m; i++) ``    ``{ ``        ``int` `x1 = q[i].x1 + 1; ``        ``int` `y1 = q[i].y1 + 1; ``        ``int` `x2 = q[i].x2 + 1; ``        ``int` `y2 = q[i].y2 + 1; `` ` `        ``int` `ans = getSum(BIT, x2, y2) -``                ``getSum(BIT, x2, y1 - 1) - ``                ``getSum(BIT, x1 - 1, y2) +``                ``getSum(BIT, x1 - 1, y1 - 1); `` ` `        ``Console.Write(``"Query({0}, {1}, {2}, {3}) = {4}\n"``, ``                ``q[i].x1, q[i].y1, q[i].x2, q[i].y2, ans); ``    ``} ``    ``return``; ``} `` ` `// Driver Code``public` `static` `void` `Main(String[] args) ``{ ``    ``int` `[,]mat = { {1, 2, 3, 4}, ``                    ``{5, 3, 8, 1}, ``                    ``{4, 6, 7, 5}, ``                    ``{2, 4, 8, 9} }; `` ` `    ``// Create a 2D Binary Indexed Tree ``    ``int` `[,]BIT = ``new` `int``[N + 1,N + 1]; ``    ``construct2DBIT(mat, BIT); `` ` `    ``/* Queries of the form - x1, y1, x2, y2 ``    ``For example the query- {1, 1, 3, 2} means the sub-matrix- ``        ``y ``        ``/\ ``    ``3 | 1 2 3 4     Sub-matrix ``    ``2 | 5 3 8 1     {1,1,3,2} --.     3 8 1 ``    ``1 | 4 6 7 5                                 6 7 5 ``    ``0 | 2 4 8 9 ``        ``| ``    ``--|------ 0 1 2 3 ---. x ``        ``| ``     ` `        ``Hence sum of the sub-matrix = 3+8+1+6+7+5 = 30 ``    ``*/``    ``Query []q = {``new` `Query(1, 1, 3, 2), ``                ``new` `Query(2, 3, 3, 3), ``                ``new` `Query(1, 1, 1, 1)}; ``    ``int` `m = q.Length; `` ` `    ``answerQueries(q, m, BIT); ``}``}`` ` `// This code is contributed by Rajput-Ji`

Output:

```Query(1, 1, 3, 2) = 30
Query(2, 3, 3, 3) = 7
Query(1, 1, 1, 1) = 6
```

Time Complexity:

• Both updateBIT(x, y, val) function and getSum(x, y) function takes O(log(NM)) time.
• Building the 2D BIT takes O(NM log(NM)).
• Since in each of the queries we are calling getSum(x, y) function so answering all the Q queries takes O(Q.log(NM)) time.

Hence the overall time complexity of the program is O((NM+Q).log(NM)) where,
N = maximum X co-ordinate of the whole matrix.
M = maximum Y co-ordinate of the whole matrix.
Q = Number of queries.

Auxiliary Space: O(NM) to store the BIT and the auxiliary array

References: https://www.topcoder.com/community/data-science/data-science-tutorials/binary-indexed-trees/

This article is contributed by Rachit Belwariar . If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.