Skip to content
Feb 25

Fenwick Trees (Binary Indexed Trees)

MT
Mindli Team

AI-Generated Content

Fenwick Trees (Binary Indexed Trees)

When you need to repeatedly calculate running totals over a list of numbers while also updating individual values, a naive approach quickly becomes a bottleneck. This is a core problem in areas like real-time analytics, frequency tracking in competitive programming, and computational geometry. The Fenwick Tree, also known as a Binary Indexed Tree (BIT), is an elegant data structure that solves this exact problem with remarkable efficiency. It allows you to compute prefix sums (the sum of the first k elements) and update any single element in time, using a simple array and a clever bit manipulation trick, all while being more memory-efficient than its more versatile cousin, the segment tree.

What is a Fenwick Tree?

A Fenwick Tree is a data structure that provides an efficient method for maintaining and querying prefix sums of an array. The fundamental operations it supports are:

  1. Update(i, delta): Add a value delta to the element at index i in the original array.
  2. Query(i): Return the sum of all elements from the beginning of the array up to index i (the prefix sum).

While a normal array can answer a query in time and update in time, or a precomputed prefix sum array can query in but update in , the Fenwick Tree balances both at . Its genius lies in its compact representation: it uses an auxiliary array of the same size as the original data, where each cell is responsible for storing the sum of a specific range of elements from the original array. The relationships between these ranges are defined entirely by the binary representation of the indices.

The Core Idea: The Least Significant Bit (LSB)

The entire Fenwick Tree logic hinges on one operation: isolating the least significant bit (LSB) of an integer's binary form. For a given index i, its LSB is the lowest-order 1 bit. You can compute it using the bitwise operation i & -i.

This LSB defines the "responsibility" of each node in the tree:

  • The value stored at index i in the Fenwick Tree array covers a range of length equal to the value of its LSB.
  • For example, index 12 (binary 1100) has an LSB of 4 (100 in binary). Therefore, tree[12] stores the sum of the original array elements from index 9 to 12 (a range of 4 elements).

This rule creates a hierarchical, tree-like structure within a flat array. To find the sum of elements up to index i, you don't sum all elements; instead, you follow a path up the tree by successively removing the LSB from i. Conversely, to update an element at index i, you follow a path up by successively adding the LSB to i, updating all nodes that are responsible for ranges containing i.

Operations: Query and Update

Let's see how the LSB rule translates into concise algorithms. We assume our Fenwick Tree array BIT is 1-indexed for mathematical elegance.

Prefix Sum Query (sum(i)) To get the prefix sum up to index i, we start at i and move backwards, adding BIT[i] to our total and then jumping to the index i - LSB(i). We repeat until i becomes 0.

function query(i):
    sum = 0
    while i > 0:
        sum += BIT[i]
        i = i - (i & -i)  # Remove the LSB
    return sum

For a range sum from l to r, you compute it as query(r) - query(l-1).

Point Update (add(i, delta)) To add delta to the original value at index i, we start at i and move forwards, adding delta to BIT[i] and then jumping to the index i + LSB(i). We repeat until i exceeds the array size n.

function update(i, delta):
    while i <= n:
        BIT[i] += delta
        i = i + (i & -i)  # Add the LSB
    return

Both operations loop at most times because each step moves to a parent node in the implicit tree, halving (for query) or moving to a covering range (for update) the distance to the root.

Advantages and Typical Applications

The primary advantage of a Fenwick Tree over a Segment Tree is its simplicity and lower constant factor. It uses exactly n+1 space, is shorter to code, and is generally faster for the specific operations it supports. However, segment trees are more versatile, capable of handling a wider variety of range queries (like minimum/maximum) and range updates.

Fenwick Trees excel in several classic problem domains:

  • Frequency Counting and Cumulative Sum: The direct use case, such as tracking frequencies and answering "how many events occurred up to time X?" queries.
  • Inversion Counting: A classic application. By processing an array from left to right and using a Fenwick Tree to query how many larger numbers have already been seen, you can count inversions in time.
  • Order Statistics (Finding the k-th Smallest): If the Fenwick Tree stores frequency counts, you can perform a binary search on the prefix sums to find the smallest index whose cumulative frequency reaches k.
  • 2D and Multidimensional Data: Fenwick Trees can be extended to two or more dimensions, allowing efficient prefix sum queries and point updates on matrices, useful in image processing or spatial data analysis.

Common Pitfalls

  1. Off-by-One Indexing: Fenwick Trees are most cleanly implemented using 1-based indexing. A frequent mistake is to use 0-based input indices without converting them to 1-based for the internal tree operations, leading to incorrect LSB calculations and infinite loops. Always convert your input index i to i+1 at the interface of your update and query functions.
  2. Initializing with Values: A Fenwick Tree is built by starting with an array of zeros and performing n update operations, each costing . Do not try to fill the BIT array directly by setting BIT[i] = arr[i], as this breaks the range-sum relationships. The correct initialization loop is for i in range(n): update(i+1, arr[i]).
  3. Confusing Point and Range Updates: The standard Fenwick Tree supports point updates and prefix sum queries. To perform a range update (add a value to every element from l to r), you need a modified approach, often involving two Fenwick Trees. Applying a standard update in a loop defeats the purpose.
  4. Overlooking Build Time: For a static array where no updates will occur, a simple precomputed prefix sum array is superior ( query, build). Only use a Fenwick Tree if your problem scenario involves interleaving updates and queries.

Summary

  • The Fenwick Tree (Binary Indexed Tree) is a compact data structure for efficiently computing prefix sums and handling point updates, both in time.
  • Its core mechanism uses the least significant bit (LSB) of an index's binary representation to define parent-child relationships and range responsibilities within a flat array.
  • It is simpler, uses less memory, and has a faster constant factor than a segment tree for the specific operations it supports, making it the preferred choice for pure prefix-sum problems.
  • Key applications include frequency counting, inversion counting, order statistics, and multidimensional cumulative data.
  • Watch out for 1-based indexing, correct initialization via updates, and remember that the standard implementation handles point updates, not arbitrary range updates.

Write better notes with AI

Mindli helps you capture, organize, and master any subject with AI-powered summaries and flashcards.