The idea: prefix sums that can still change

You have an array A[1..n] and two jobs: change one element, and ask for a prefix sum sum(i) = A[1] + … + A[i]. A plain array makes the change O(1) but the sum O(n). A prefix-sum array makes the sum O(1) but a change O(n). A Fenwick tree, also called a binary indexed tree (BIT), does both in O(log n) with one extra array T[1..n] of the same size.

The 16 boxes of the page's Fenwick tree drawn as bars over the array A = 5 2 9 1 7 3 8 6 4 2 5 7 1 3 6 8. Odd indices have one-cell boxes, 2, 6, 10, 14 two-cell boxes, 4 and 12 four-cell boxes, 8 an eight-cell box and 16 the whole array. Each index is also written in 5-bit binary.
The page's starting tree: box T[i] ends at index i and is lowbit(i) cells long, so T[12] = A[9..12] = 18 and T[16] = A[1..16] = 77.

Box T[i] holds the sum of the lowbit(i) elements that end at i: T[i] = A[i − lowbit(i) + 1] + … + A[i]. On the canvas each box is a bar over the cells it covers, one row per box length, and every index is written in binary underneath. Indices are 1-based: index 0 has no lowest bit, so it is not used.

lowbit(i) = i & −i

lowbit is the value of the lowest 1 bit of i: lowbit(12) = lowbit(01100) = 00100 = 4. Computers store −i in two's complement: invert every bit and add 1. The +1 carries through the trailing 1s of the inverted number, so −i agrees with i on the lowest 1 bit and the zeros below it, and is the opposite everywhere above. i & −i keeps just that one bit (Demo: lowbit(12) = 12 & −12 = 4).

binary (5 bits)
1201100
invert10011
−12 = invert + 110100
12 & −1200100 = 4

Prefix sum: walk down

To get sum(i), add T[i], which covers the last lowbit(i) cells, then jump to the cell just before that block: i −= lowbit(i). That clears the lowest 1 bit of i, so the walk stops after as many boxes as i has 1 bits, at most log₂ n + 1.

int sum(int i) {
    int s = 0;
    for (; i > 0; i -= i & -i)
        s += T[i];
    return s;
}

For 13 = 01101 the walk visits 13, 12 = 01100 and 8 = 01000: T[13] + T[12] + T[8] = A[13] + A[9..12] + A[1..8] = 1 + 18 + 41 = 60 (Demo: sum(13)). 15 = 01111 has four 1 bits, the most of any index up to 16, so it needs four boxes (Demo: sum(15), the worst case), while sum(16) is just T[16]. On the canvas the visited boxes turn blue, and so do the cells they cover: together they are exactly A[1..i], with no gaps and no overlap.

Top: the boxes visited by sum(13), T[13], T[12] and T[8], in blue; they cover A[1..13]. Bottom: the boxes changed by add(5, +3), T[5], T[6], T[8] and T[16], in green; each of them covers A[5].
A query walks down by clearing the lowest 1 bit; an update walks up by adding it. The two paths are different sets of boxes.

Update: walk up

To add d to A[i], every box whose range contains i must change. The first is T[i]. The next box that also covers i is the parent i + lowbit(i): adding the lowest 1 bit makes the index's lowbit at least twice as big, so its box reaches back past i. Repeat until the index passes n.

void add(int i, int d) {
    for (; i <= n; i += i & -i)
        T[i] += d;
}

Adding 3 to A[5] changes T[5], T[6], T[8] and T[16] (5 = 00101 → 00110 → 01000 → 10000), and nothing else (Demo: add 3 to A[5]). A later query then sees the change, because the boxes it adds are exactly the updated ones that lie inside its prefix (Demo: add 2 to A[3], then sum(7) sees it: 37 instead of 35).

Range sums and cost

A Fenwick tree answers prefix sums only, but any range is the difference of two prefixes: A[l..r] = sum(r) − sum(l − 1). For A[5..11] that is 52 − 17 = 35 (Demo: range sum A[5..11]; the boxes of the second walk are drawn red).

Plain arrayPrefix-sum arrayFenwick treeSegment tree
Change one elementO(1)O(n)O(log n)O(log n)
Prefix or range sumO(n)O(1)O(log n)O(log n)
Extra memorynonennabout 2n to 4n
Range min / maxO(n)nono (needs an inverse)yes

The Fenwick tree needs the operation to have an inverse (sum and difference, XOR) so that ranges can be subtracted. A segment tree also handles min and max and lazy range updates, at the cost of more memory and code. Like a binary heap, the tree is implicit: there are no pointers, only index arithmetic on one array.

Building the tree

Calling add once per element builds the tree in O(n log n). The page builds it in O(n): set T[i] = A[i], and for i = 1 to n add T[i] into its parent T[i + lowbit(i)]. Each box is complete before it passes its total up.

Fenwick trees count inversions, keep running frequency tables (how many values are ≤ x), and serve order-statistic queries in competitive programming; they were introduced for arithmetic coding, where the encoder needs cumulative symbol frequencies that keep changing.

For the same operations on a segment tree, side by side, see Segment Tree vs Fenwick Tree.

What the page leaves out

The page fixes n = 16 so every index fits in 5 bits. It leaves out the 0-based variant (i = (i & (i + 1)) − 1 and i |= i + 1), range updates with a second tree, finding the smallest i with sum(i) ≥ x by binary lifting over the powers of two, 2D Fenwick trees for matrix sums, and other invertible operations such as XOR.