Fenwick Tree (Binary Indexed Tree)
Point updates and prefix sums, range sums, coordinate compression, inversion counting, frequency order statistics, range update variants, and 2D Fenwick trees.
Typical operations: O(log n) update and prefix query, O(log n) range sum via prefix differences.
How it works
Index i (1-based) stores the sum of the range (i − lowbit(i), i], where lowbit(i) = i & −i. A prefix query walks i → i − lowbit(i), an update walks i → i + lowbit(i); each loop touches at most log₂ n cells.
Output (g++ 11.2, -std=c++17, warnings as errors, AddressSanitizer + UndefinedBehaviorSanitizer; Ubuntu 22.04 on WSL2):
Range-update/point-query uses a Fenwick tree over the difference array (Module 5); range-update/range-query uses two Fenwick trees. A 2-D Fenwick tree nests the loops for O(log² n) operations on a grid.
#include <bits/stdc++.h>
using namespace std;
struct Fenwick {
int n; vector<long long> t;
explicit Fenwick(int n_) : n(n_), t(n_ + 1, 0) {}
void add(int i, long long v) { for (++i; i <= n; i += i & -i) t[i] += v; } // 0-based public index
long long prefix(int i) const { long long s = 0; for (; i > 0; i -= i & -i) s += t[i]; return s; } // sum of [0, i)
long long range(int l, int r) const { return prefix(r) - prefix(l); } // [l, r)
int lowerBound(long long target) const { // smallest i with prefix(i+1) >= target (non-negative values)
int pos = 0; long long acc = 0;
for (int step = 1 << 20; step; step >>= 1)
if (pos + step <= n && acc + t[pos + step] < target) { pos += step; acc += t[pos]; }
return pos;
}
};
int main() {
Fenwick f(8);
vector<int> a = {5, 2, 9, 4, 7, 1, 3, 6};
for (int i = 0; i < 8; ++i) f.add(i, a[i]);
cout << "sum [2, 6) = 9+4+7+1 = " << f.range(2, 6) << '\n';
f.add(3, 10); // a[3] += 10
cout << "after a[3] += 10: sum [2, 6) = " << f.range(2, 6) << '\n';
cout << "cells covered by t[i]:";
for (int i =
…sum [2, 6) = 9+4+7+1 = 21
after a[3] += 10: sum [2, 6) = 31
cells covered by t[i]: t1=(0,1] t2=(0,2] t3=(2,3] t4=(0,4] t5=(4,5] t6=(4,6] t7=(6,7] t8=(0,8]
inversions in {1000000,3,77,3,-50,12}: 10
3rd smallest of {42,7,99,7,15}: 15
20000 random updates/queries match a plain arrayQuiz
? Which cells does t[6] cover in a 1-based Fenwick tree?
+ (4, 6] :: lowbit(6) = 2, so it covers 2 elements ending at 6.
- (0, 6] :: That would be t[8]-style coverage.
- (5, 6] :: lowbit(6) is 2, not 1.
- [6, 8) :: No.
? Why can a Fenwick tree answer range sums but not range minimums by subtraction?
+ Sums are invertible (subtract one prefix from another); minimum is not. :: Use a segment tree or sparse table for min.
- Minimum is too slow to compute. :: It is O(1) per merge.
- Fenwick trees only store counts. :: They store any group operation.
- They can. :: Not by prefix subtraction.
? What do the update loop `i += i & -i` and query loop `i -= i & -i` cost?
+ O(log n) each :: Each step changes the lowest set bit.
- O(1) :: No.
- O(√n) :: That is sqrt decomposition.
- O(n) :: No.