Fenwick tree
A compact array that keeps running totals so you can add to one item and get any prefix sum in O(log n).
O(log n) per add or prefix sumSpace O(n)7 practice problemsStep-through pictureThe idea
A Fenwick tree, also called a binary indexed tree, solves the same problem as a segment tree for sums: change single items and ask for range sums, both in O(log n). It is shorter to write and uses an array of just n + 1 numbers.
Each cell tree[i] (counting from 1) stores the sum of a block of items that ends at item i. The block's length is the lowest set bit of i in binary, written i & -i. For example tree[6] covers 2 items (6 is 110), tree[8] covers 8 items (8 is 1000), and tree[7] covers 1 item.
To get the sum of the first i items, add tree[i], then jump to the item just before that block (i -= i & -i), and repeat. To add to an item, update every block that contains it by jumping the other way (i += i & -i). Both walks take about log n jumps.
An everyday example
Counting pages with bookmarks
A long notebook has bookmarks of different sizes: some cover 1 page, some 2, some 4, some 8, and each bookmark has the total of the numbers on the pages it covers written on it. To total the first 7 pages, you read the bookmark for page 7 (1 page), then the one for pages 5 to 6, then the one for pages 1 to 4: three bookmarks instead of seven pages. When page 3 changes, you fix only the bookmarks that cover page 3.
| In the example | In the code |
|---|---|
| A bookmark and its total | tree[i] |
| How many pages a bookmark covers | i & -i, the lowest set bit |
| Jumping to the bookmark before this one | i -= i & -i |
| Fixing every bookmark that covers a page | i += i & -i |
From the slow way to fenwick tree
- The problem is the same as for a segment tree: change single items and ask for range sums, many times, mixed together. A prefix-sum array answers in one step but needs up to
nsteps per change. A segment tree does both inO(log n), but it needs4nslots and a few recursive methods. Can a plain array ofnnumbers do the same job? - Look at how a prefix is made of blocks. Any whole number is a sum of powers of two:
7 = 4 + 2 + 1. So the first 7 items split into a block of 4 (items 1 to 4), a block of 2 (items 5 to 6), and a block of 1 (item 7). If each of those block sums were stored, a prefix sum would be just 3 additions, one per1bit in the binary form of 7. - Which block should position
istore? Lettree[i]hold the block that ends at itemiand is as long as the lowest set bit ofi, writteni & -i. Every position stores exactly one block, so the array hasn + 1cells, and the blocks a prefix needs are found by takingtree[i]and then jumping toi - (i & -i), which drops the lowest1bit. - When one item changes, only the blocks that contain it need fixing. Starting at its position and jumping
i += i & -ivisits exactly those blocks, each longer than the last, so there are at most aboutlog₂ nof them. One array, two short loops, and the lowest-set-bit trick: that is a Fenwick tree.
How it works
- Create
treewithn + 1zeros. Index0is unused, because the jumps rely on 1-based positions. add(index, delta): start ati = index + 1and adddeltatotree[i].- Move to the next block that also contains this item:
i += i & -i. Stop whenipasses the end. prefixSum(index): start ati = index + 1withtotal = 0. Addtree[i].- Move to the block just before:
i -= i & -i. Stop whenireaches0, and returntotal. rangeSum(left, right)isprefixSum(right)minusprefixSum(left - 1).
Watch it run
This picture runs the code below on a real input. Press Step to move one step at a time, or Play to watch. The highlighted line is the one that just ran. Change the input to see other cases.
See every step at onceThe same run, laid out side by side
The code
Point at a note to light up the lines it explains.
class FenwickTree {constructor(n) {this.tree = new Array(n + 1).fill(0);}add(index, delta) {for (let i = index + 1; i < this.tree.length; i += i & -i) {this.tree[i] += delta;}}prefixSum(index) {let total = 0;for (let i = index + 1; i > 0; i -= i & -i) {total += this.tree[i];}return total;}rangeSum(left, right) {return this.prefixSum(right) - (left > 0 ? this.prefixSum(left - 1) : 0);}}
How fast it is
| Time | O(log n) per add or prefix sum |
|---|---|
| Extra memory | O(n) |
Each jump changes the lowest set bit of i, so a walk has at most about log₂ n jumps. The tree is one array of n + 1 numbers.
- Best case
O(1)prefixSum(0)reads onlytree[1], thenibecomes0. Anaddto a position whose next jump is past the end also takes one step. - Average case
O(log n)A
prefixSumtakes one step per1bit inindex + 1, about half of thelog₂ nbits for a random index. - Worst case
O(log n)Positions with many
1bits forprefixSum, such as 511 (111111111), andaddat position 1, which climbs 1, 2, 4, 8, and so on. For 1,000 items, a prefix sum takes at most 9 jumps and an add at most 10.
Common mistakes
- Using 0-based positions inside the loops.
0 & -0is0, soinever moves and the loop runs forever. Shift to 1-based withindex + 1. - Setting a value with
add(index, value)instead ofadd(index, value - current). A Fenwick tree adds changes; keep the current values in a separate array if you need to set. - Using it for min or max with updates that can make values bigger and smaller. Sums can be undone by subtracting, but a minimum can't; use a segment tree there.
- Forgetting the
left > 0check, which callsprefixSum(-1).
When to use it
Look for these clues in a problem:
- You need prefix sums or range sums while single items keep changing.
- You need to count, for each item, how many earlier items are smaller (inversions, ranks), often after compressing values to small indexes.
- You need to add to a range and read single items (store differences in the tree).
- Memory or code size matters, and the operation is a sum (or anything you can undo, like XOR).
Check yourself
Answer each one in your head first, then open it.
Which cells does add(2, 5) change when there are 7 items?
tree[3] and tree[4]. The next jump goes to position 8, which doesn't exist for 7 items, so the loop stops.
Which items does tree[6] cover?
Positions 5 and 6, which are indexes 4 and 5, because 6 & -6 is 2: a block of 2 that ends at position 6.
Why does prefixSum(6) take exactly 3 jumps?
It starts at position 7, which is 111 in binary. Each jump removes one 1 bit (7, then 6, then 4, then 0), so it takes as many jumps as there are 1 bits.
Why can a Fenwick tree answer range sums but not range minimums?
A range sum is prefixSum(right) - prefixSum(left - 1). There is no way to "subtract" the minimum of the first part from the minimum of a longer part to get the minimum of what's left.
Practice problems
Stuck on one? Tuto is in the playground too, and gives you hints, never the answer.
0 of 7 solved. Solve one to earn the bronze medal, half for silver, and all of them for gold.
Start practicingGo further
You don't need these to start practicing. Open one when you want more.
Why it works
The reasoning that makes it always right
The tree keeps one property: tree[i] is the sum of the items at positions i - (i & -i) + 1 to i, counting positions from 1. When the tree is all zeros, every block sum is 0, so it holds. Every later change goes through add, which must keep it.
prefixSum is right because its blocks fit together. The block at i starts at i - (i & -i) + 1, and the next jump goes to i - (i & -i), whose block ends exactly one position before. So the blocks visited touch end to end, never overlap, and stop at position 1 when i reaches 0. Their sum is the sum of positions 1 to index + 1, which is items 0 to index.
add is right because it visits exactly the blocks that contain the item. A block ending at i contains position p when i >= p and the block reaches back far enough. Adding the lowest set bit to i gives the next position whose block is long enough to reach back over the current block, and so over p. Positions in between have shorter blocks that start after position i, so they can't contain p. Each jump makes the lowest set bit bigger, so there are at most about log₂ n jumps, and the loop ends when i passes the end.
Going deeper
3 more ideas
What i & -i means
In binary, -i flips all bits of i and adds one, so i & -i keeps only the lowest 1 bit of i. For i = 6 (110) it is 2 (10); for i = 8 (1000) it is 8; for any odd i it is 1. Cell tree[i] covers exactly that many items, ending at item i.
Cost
Each jump in prefixSum removes the lowest set bit of i, and each jump in add moves the lowest set bit up, so both loops run at most about log₂ n times. Building by calling add for every item is O(n log n). The array has n + 1 numbers: O(n) space.
Range updates with point reads
Store differences instead of values: to add v to items l to r, call add(l, v) and add(r + 1, -v). Then prefixSum(i) is the current value of item i. This is the difference-array idea, made fast for many updates and reads mixed together.
Work it by hand
Every step in a table, with why
Seven numbers are already added, so tree = [0, 6, 4, 4, 9, 3, 8, -1]. Add 5 to index 2, then ask for the sum of indexes 2 to 6. Each row is one turn of a loop.
nums = [6, -2, 4, 1, 3, 5, -1], add(2, 5), then rangeSum(2, 6)
| Step | Call | i | i & -i | tree[i] | total | What happens | Why |
|---|---|---|---|---|---|---|---|
| 1 | add(2, 5) | 3 | 1 | 4 to 9 | - | next i = 4 | Index 2 lives at position 3. tree[3] covers 1 item, item 3 itself, so it gets +5. |
| 2 | add(2, 5) | 4 | 4 | 9 to 14 | - | next i = 8 | 3 + 1 = 4. tree[4] covers positions 1 to 4, which include position 3, so it gets +5 too. |
| 3 | add(2, 5) | 8 | - | - | - | 8 is not < 8: stop | There is no tree[8] for 7 items, so every block holding index 2 is now fixed. |
| 4 | prefixSum(6) | 7 | 1 | -1 | -1 | next i = 6 | Index 6 is position 7. tree[7] covers only position 7. |
| 5 | prefixSum(6) | 6 | 2 | 8 | 7 | next i = 4 | 7 - 1 = 6. tree[6] covers positions 5 and 6: 3 + 5 = 8. |
| 6 | prefixSum(6) | 4 | 4 | 14 | 21 | next i = 0 | 6 - 2 = 4. tree[4] covers positions 1 to 4, already including the +5. |
| 7 | prefixSum(6) | 0 | - | - | 21 | i > 0 fails: return 21 | Three blocks, 7, 5..6, and 1..4, covered every position from 1 to 7 exactly once. |
| 8 | prefixSum(1) | 2 | 2 | 4 | 4 | next i = 0 | left = 2, so subtract prefixSum(1). Position 2's block covers positions 1 and 2: 6 + (-2) = 4. |
| 9 | prefixSum(1) | 0 | - | - | 4 | return 4 | One block was enough. rangeSum returns 21 - 4 = 17. |
rangeSum(2, 6) returns 17, which matches 9 + 1 + 3 + 5 + (-1) after the change. The add touched 2 cells, and the two prefix sums read 3 cells and 1 cell, because 7 is 111 in binary and 2 is 10.
Compared with other ways
When to pick something else
| Approach | Time | Extra memory | Choose it when |
|---|---|---|---|
| Fenwick tree | O(log n) | O(n) | Per add or prefix sum. Pick it for sums (or XOR, or counts) with single-item changes: shortest code and n + 1 numbers. |
| Segment tree | O(log n) | O(n) | You need min or max, which can't be subtracted, or lazy range updates, or a node that stores several values. |
| Prefix-sum array | O(n) | O(n) | That O(n) is the cost of a change; a query is O(1). Pick it when the data rarely changes. |
| Square-root blocks | O(sqrt n) | O(n) | You need an operation that doesn't fit either tree, and sqrt n steps per query is fast enough. Split the array into blocks of about sqrt n items with one total each. |
Extra memory: O(n): one array of n + 1 numbers, no recursion, and no other memory.
How the steps grow
- Fenwick tree, Segment tree
O(log n) - Prefix-sum array
O(n) - Square-root blocks
O(sqrt n)
| Approach | n = 10 | n = 1,000 | n = 1,000,000 |
|---|---|---|---|
| Fenwick tree | 3 | 10 | 20 |
| Segment tree | 3 | 10 | 20 |
| Prefix-sum array | 10 | 1,000 | 1 million |
| Square-root blocks | 3 | 32 | 1,000 |
Inputs that need care
5 tricky inputs
- An index past the end, such as
prefixSum(7)with 7 items - It reads
tree[8], which isundefined, sototalbecomesNaN. The code doesn't check bounds; make sureindex < nbefore calling. - An empty tree,
new FenwickTree(0) adddoes nothing because1 < 1is false, butprefixSum(0)readstree[1]and returnsNaN. Check forn === 0first.left = 0inrangeSum- The
left > 0check skips the subtraction, sorangeSum(0, right)is justprefixSum(right). Without that check it would callprefixSum(-1). - Negative values, such as
-2and-1above - Nothing changes: the blocks just store sums, and sums of negative numbers work the same way.
- Decimal values, such as prices like
0.1 - Floating-point sums drift a little after many adds. Store whole numbers, such as cents, when the totals must be exact.
Variations and follow-ups
Twists interviewers add
Build in O(n)
Instead of calling add for every item, which costs O(n log n), copy the items into tree[1..n], then for each i from 1 to n add tree[i] into tree[i + (i & -i)] if that position exists. For the trace's seven numbers this gives the same [0, 6, 4, 4, 9, 3, 8, -1].
Range add with range sum
Keep two Fenwick trees, one for differences and one for differences times their position. A range add becomes four add calls, and a range sum becomes a few prefix sums combined with a short formula. Everything stays O(log n).
Counting smaller items before each item
Map values to small ranks, walk the list from left to right, and for each value ask prefixSum(rank - 1) before calling add(rank, 1). The answers count, for each item, how many earlier items are smaller. Summing the opposite counts gives the number of inversions.
Find the first prefix that reaches a total
To find the smallest index whose prefix sum is at least x (all values non-negative), walk down powers of two from the largest: jump forward by a power whenever that block's sum still fits under x. This finds the answer in O(log n) without a separate binary search.
In an interview
Spot it, explain it, answer follow-ups
- Spot it from "prefix sum" or "range sum" with "update an item", or from "for each item, count earlier items that are smaller", which becomes a Fenwick tree over value ranks.
- Explain
i & -iwith one example, such as6(110) giving2, and say what blocktree[6]covers: positions 5 and 6. Then the two loops are easy to follow. - Test
rangeSum(0, 0), the whole range, and a range right after anaddinside it. Also say out loud why positions start at 1:0 & -0is0, so a loop at position 0 would never move. - A usual follow-up is "can it do range minimum?". Answer no, not with this trick: a range sum is a difference of two prefix sums, but a minimum can't be subtracted. Use a segment tree or a sparse table.
Where frontend code uses it
The same idea in real UI code
- A virtualized list with resizable rows can store row heights in a Fenwick tree: the offset of row
kis a prefix sum, and resizing one row is a singleadd. - Analytics dashboards that count events per time bucket while events keep arriving can answer "events between minute
aand minuteb" with two prefix sums. - Ranking features, such as showing "you are faster than 83% of players" while scores stream in, count how many scores are below a value with a Fenwick tree over score buckets.