Fenwick tree
A Fenwick tree, or binary indexed tree, is one array of partial sums. Cell i holds the sum of a block ending at i, and the block's length is i's lowest 1 bit. Adding that bit moves to the next cell to update; clearing it moves to the next block of a prefix sum.
58632726
tree[i], labelled by i in binary
0
10
100
110
1000
1010
1100
1110
1000Add the 8 values into a Fenwick tree, then sum positions 0 to 6. Cell i holds the sum of the last lowbit(i) positions up to i, where lowbit is i's lowest 1 bit.
1function add(tree, i, delta) {2 for (i++; i < tree.length; i += i & -i) tree[i] += delta;3}45function prefixSum(tree, i) {6 let sum = 0;7 for (i++; i > 0; i -= i & -i) sum += tree[i];8 return sum;9}Keys: Space play or pause, ← → step. The URL always points at the frame you are on.
What it costs
| Case | Time | When |
|---|---|---|
| best | 1 | a prefix whose length is a power of two: one cell |
| average | log n | per prefix sum or per update |
| worst | log n | one cell per 1 bit of the index |
| space | n | one cell per value, no pointers |
Where it breaks
- Off-by-one indexes.
i & -iis 0 when i is 0, so the loop would never move. That is why the tree counts from 1 and both functions start withi++. Mixing 0-based and 1-based indexes is the usual Fenwick bug. - Powers of two are cheap. Pick Sum up to 7: 8 positions is 1000 in binary, one 1 bit, so the answer is a single cell. Sum up to 6 is 7 positions, 111 in binary, so it takes three.
- Less flexible than a segment tree. It does prefix sums, and so any range sum by subtracting two of them, in less code and memory. For range minimum or maximum, use a segment tree.