Motivation:
Given a 1D array of n elements. [2, 5, -1, 3, 6]
range sum query: what's the sum from 2nd element to 4th element query(2, 4)? 5 + (-1) + 3 = 7
Native implementation: O(n) per query.
Use DP to pre-compute the prefix sums in O(n), [2, 5, -1, 3, 6] -> [2, 7, 6, 9, 15]
reduce query to O(1). query(2, 4) = sums(n1....n4) - sums(n1....n1) = sums[4-1] - sums[1-1] = 9 - 2 = 7
what if the value of elements can change? O(n)
Fenwick tree was proposed to solve the prefix sum problem.
The idea is to store partial sum in each node and get total sum by traversing the tree from leaf to root. the tree has a height of log(n)
Query: O(log(n))
Update: O(log(n))
class FenwickTree { public: FenwickTree(int n): sums_(n+1, 0) {} void update(int i, int delta) { while (i < sums_.size()) { sums_[i] += delta; i += lowbit(i); } } int query(int i) const { int sum = 0; while (i > 0) { sum += sums_[i]; i -= lowbit(i); } return sum; } private: static inline int lowbit(int x) { return x & (-x); } vector<int> sums_; };