How Fenwick Trees Use the LSB for Prefix Sums

A Fenwick tree, also known as a Binary Indexed Tree (BIT), is a data structure that calculates prefix sums and updates elements in an array in \(O(\log n)\) time. It achieves this efficiency by exploiting the binary representation of array indices—specifically the Least Significant Bit (LSB). This article explains how the LSB determines the range of elements each tree node stores, and how bitwise manipulation enables rapid prefix sum queries and point updates.


Isolating the Least Significant Bit

The Least Significant Bit of an integer is the lowest set bit (value of 1) in its binary representation. In two’s complement binary arithmetic, a positive integer \(i\) and its negation \(-i\) share only one set bit: the lowest one.

You can isolate the LSB using the bitwise AND operator:

\[\text{LSB}(i) = i \ \& \ (-i)\]

Examples:


Range of Responsibility

In a 1-indexed Fenwick tree array BIT[], each index \(i\) does not store a single element; instead, it stores the sum of a contiguous sub-array of the original array \(A[]\).

The length of this sub-array is equal to \(\text{LSB}(i)\), covering the index range:

\[(i - \text{LSB}(i), i] \quad \text{or} \quad [i - \text{LSB}(i) + 1, i]\]

Odd indices have an LSB of \(1\), so they store only their own single value. Powers of two (\(2, 4, 8, \dots\)) store the complete prefix sum from index \(1\) up to that power of two.


Querying Prefix Sums: Subtracting the LSB

Any integer \(k\) can be uniquely represented as a sum of powers of two. To calculate the prefix sum from \(1\) to \(k\), the range \([1, k]\) is decomposed into at most \(\log_2(k)\) disjoint intervals.

To retrieve the prefix sum: 1. Add the value at \(\text{BIT}[k]\) to the total sum. 2. Remove the lowest set bit: \(k \leftarrow k - (k \ \& \ -k)\). 3. Repeat until \(k = 0\).

Example: Querying the Prefix Sum up to Index 7


Updating Elements: Adding the LSB

When an element at index \(k\) in the original array is modified by adding a value val, every interval in the Fenwick tree that encompasses index \(k\) must be updated.

To propagate the update: 1. Add val to \(\text{BIT}[k]\). 2. Move to the next encompassing range by adding the lowest set bit: \(k \leftarrow k + (k \ \& \ -k)\). 3. Repeat while \(k \le n\) (where \(n\) is the array size).

Example: Updating Index 3


Summary of Operations

Operation Action on Index \(k\) Binary Effect Time Complexity
Prefix Sum \(k \leftarrow k - (k \ \& \ -k)\) Clears the least significant set bit \(O(\log n)\)
Point Update \(k \leftarrow k + (k \ \& \ -k)\) Cascades carries to cover larger intervals \(O(\log n)\)