0% completed
A Binary Indexed Tree is designed to efficiently compute prefix sums and handle updates in logarithmic time. It achieves this by storing cumulative information at specific indices, enabling quick retrieval and updates.
For an input array of size n
, the BIT is typically represented as an array of size n + 1
, with the 0-th index left unused for simplicity. The key idea is that each index in the BIT array represents a sum of elements from the input array, covering different ranges.
The structure of a BIT can be visualized as a tree where each index is connected to its parent. The parent index is determined using the following formula:
\text{parent}(i) = i - (i \& -i)
In simpler terms, you can get the parent index by flipping the rightmost set bit in the binary representation of (i).
In the diagram below, we have shown the Binary Indexed Tree for array having 10 elements.
To help visualize the tree structure, let’s consider the indices and how they relate to their parent nodes.
Index | Binary Value | Flip Last Set Bit | Parent Index |
---|---|---|---|
1 | 0001 | 0000 | 0 |
2 | 0010 | 0000 | 0 |
3 | 0011 | 0010 | 2 |
4 | 0100 | 0000 | 0 |
5 | 0101 | 0100 | 4 |
6 | 0110 | 0100 | 4 |
7 | 0111 | 0110 | 6 |
8 | 1000 | 0000 | 0 |
9 | 1001 | 1000 | 8 |
10 | 1010 | 1000 | 8 |
11 | 1011 | 1010 | 10 |
This table helps visualize how each index in the BIT connects to its parent, forming a tree-like structure.
Let's take the array [3, 2, -1, 6, 5, 4, -3, 3, 7, 2, 3]
and see how a Binary Indexed Tree (BIT) stores the range of sums at different nodes. Each node in the BIT represents a cumulative sum over a specific range of indices, determined by the binary representation of the node's index.
2
is 10
in binary.2
).i - (i & -i)
to i-1
, the range is 2 - 2
to 1
, which gives 0
to 1
.bit[2]
will store the sum of the elements at indices 1
and 2
, which are 3 + 2 = 5
.4
is 100
in binary.4
).4 - 4
to 4-1
, which gives 0
to 3
.bit[4]
will store the sum of elements at indices 1
through 4
, which are 3 + 2 - 1 + 6 = 10
.6
is 110
in binary.2
).6 - 2
to 5
, which gives 4
to 5
.bit[6]
will store the sum of elements at indices 5
and 6
, which are 5 + 4 = 9
.To find the sum of elements from index 0
to 6
using a Binary Indexed Tree (BIT), we combine the values stored in specific nodes of the BIT that cover this range.
Start at Node 7:
bit[7]
stores the sum of the range (6, 6)
.sum = -3
.Move to Node 6:
bit[6]
stores the sum of the range (4, 5)
.sum = sum + bit[6] = -3 + 9 = 6
.Move to Node 4:
bit[4]
stores the sum of the range (0, 3)
.sum = sum + bit[4] = 6 + 10 = 16
.The final result is the sum of the elements from index 0
to 6
, which is 16
. This approach leverages the BIT structure to achieve the sum in logarithmic time complexity, as it only needs to visit a few nodes rather than summing directly from the array.
Constructing a Binary Indexed Tree (BIT) involves building the tree structure from a given array. The BIT will store cumulative sums that allow efficient range queries and updates.
Initialize the BIT:
bit[]
of the same length as the input array, initialized to 0
.Populate the BIT:
update
function.Update Function:
update
function adds the value of the current element to the appropriate indices in the BIT.update()
function in the next part.The update()
function is essential in maintaining the Binary Indexed Tree (BIT). When an element in the original array is modified, we need to update the BIT to reflect this change efficiently. This function ensures that the BIT remains consistent, allowing for quick prefix sum queries.
Identify the Starting Index:
1
.Update the BIT at the Current Index:
bit[index]
.Move to the Next Node Using index += (index & -index)
:
index += (index & -index)
moves the index to the next node in the BIT that needs to be updated.(index & -index)
isolates the rightmost set bit in the binary representation of index
.index
, corresponding to the size of the range that this node covers.Repeat Until the End of the BIT:
Index 5 (Binary: 101
):
(index & -index)
gives 1
(binary 001
).5
to 6
(binary 110
).5
covers just index 5
, while node 6
covers indices 5
to 6
(1-based).Index 6 (Binary: 110
):
(index & -index)
gives 2
(binary 010
).6
to 8
(binary 1000
).6
covers indices 5
and 6
, while node 8
covers indices 1
to 8
(1-based).This method of moving ensures that only the necessary nodes are updated, keeping the BIT efficient.
Let's understand the below node updating examples with a diagram.
update()
function is called, which runs in O(log n) time.The getSum()
function in a Binary Indexed Tree (BIT) calculates the prefix sum from the start of the array up to a given index. This operation is efficient and crucial for range queries.
Initialize the Sum:
sum = 0
.Adjust Index for 1-Based BIT:
index++
.Iterate Over the BIT Using a While Loop:
bit[index]
to sum
.index -= (index & -index)
. This moves to the parent node, which represents a range covering fewer elements.index
becomes 0
.Return the Result:
sum
, which now contains the prefix sum up to the original index.getSum()
function runs in O(log n) time. This is because, in the worst case, the while loop will execute log n times, moving from the given index to the root of the Binary Indexed Tree.sum
variable) and does not depend on the size of the input array or BIT.Now, let's start solving the problems on the Binary Indexed Tree pattern.
.....
.....
.....