Fenwick Tree (Binary Indexed Tree)
A segment tree is general but bulky — 4n memory and a dozen lines per operation. When all you need is prefix sums with point updates, the Fenwick tree (a.k.a. Binary Indexed Tree, BIT) does the same job in n memory and about three lines per operation. It’s the structure competitive programmers reach for first because it’s so short to type.
What it computes
A BIT supports, over an array of length n:
update(i, delta)— adddeltatoarr[i], in O(log n).prefixSum(i)— the sum ofarr[1..i], in O(log n).
And a range sum sum(i, j) is just prefixSum(j) − prefixSum(i − 1). That’s it — point update + prefix query, and everything else is built from those two.
The core idea: each index covers a power-of-two block
The magic is in how the tree array bit[] is laid out. bit[i] stores the sum of a block of arr ending at index i, whose length is the lowest set bit of i. That “lowest set bit” is computed by the famous trick:
lowbit(i) = i & (-i)Because of two’s-complement, i & -i isolates the lowest 1-bit of i. For example lowbit(12) = lowbit(1100₂) = 100₂ = 4, so bit[12] covers arr[9..12] (4 elements). lowbit(6) = lowbit(110₂) = 10₂ = 2, so bit[6] covers arr[5..6].
i & -i is the whole Fenwick tree in one expression. In two’s complement, -i is ~i + 1, which flips every bit above the lowest set bit and leaves the lowest set bit intact — so i & -i keeps exactly that lowest 1-bit. That value is both the size of the block index i is responsible for and the jump distance you add or subtract to walk the implicit tree. Everything else follows from it. (See Day 17 — Bit Manipulation for why i & -i isolates the low bit.)
The two loops
The beauty is that “walk the tree” is just repeatedly adding or subtracting lowbit:
update(i, delta)— move up, hitting every block that containsi: start ati, addlowbit(i)each step until pastn.prefixSum(i)— move down, accumulating disjoint blocks that tile[1..i]: start ati, subtractlowbit(i)each step until 0.
Both loops run at most log₂ n times because each step clears (or moves past) one bit.
The Fenwick tree is 1-indexed, always. Index 0 is unusable because lowbit(0) = 0, so the update loop i += i & -i would never advance — an infinite loop. Shift your data to start at index 1 (update(i + 1, ...) if your array is 0-based). This off-by-one is the single most common BIT bug.
BIT vs segment tree — when to use which
| Fenwick (BIT) | Segment tree | |
|---|---|---|
| Memory | n | 4n |
| Code length | ~3 lines/op | ~10 lines/op |
| Operations | sum / prefix-sum (and invertible ops) | any associative op (min, max, gcd, …) |
| Range update | needs difference-array trick | natural with lazy propagation |
| Range min/max | no (not invertible) | yes |
The deciding factor: BIT only works for invertible aggregates (sum is invertible — you can subtract; min and max are not). If you need range min or max, you need a segment tree. If you need prefix sums, the BIT is shorter, smaller, and faster by a constant factor.
Range update, point query (the difference-array trick)
A BIT naturally does point update, range query. To flip it to range update, point query — “add v to all of [i, j], then read a single index” — store a difference array in the BIT: update(i, +v) and update(j + 1, −v). Then prefixSum(k) gives the total amount added at index k. Two BITs combined give range update + range query, but that’s rarely needed in interviews.
Quick check
Next: Basic Questions — warm-ups for both structures, then the practice set.