Fenwick tree: prefix sums with updates
Picture
Values [2,1,3,4] answer sums quickly, but changing position 1 requires fixing every later stored prefix.
Predict
Can ordinary prefix sums handle many updates in O(1) each?
Walk through the small example
No. The operation has an inverse, and binary-indexed blocks decompose any prefix.
Mental model and complete Python solution
Each index participates in a ladder of increasingly large blocks. An update climbs to every block containing the point; a query descends through disjoint blocks covering the prefix.
What the function promises: Fenwick(n) supports zero-based point additions and inclusive range sums. Invalid indices raise ValueError.
class Fenwick:
def __init__(self, n):
self.n, self.tree = n, [0] * (n + 1)
def add(self, index, delta):
if not 0 <= index < self.n:
raise ValueError("Invalid index")
i = index + 1
while i <= self.n:
self.tree[i] += delta
i += i & -i
def prefix(self, end):
total = 0
i = min(end + 1, self.n)
while i > 0:
total += self.tree[i]
i -= i & -i
return total
def range_sum(self, left, right):
return self.prefix(right) - self.prefix(left - 1)
bit = Fenwick(4)
for i, value in enumerate([2,1,3,4]): bit.add(i, value)
assert bit.range_sum(1,3) == 8
bit.add(1,4)
assert bit.range_sum(1,3) == 12
Work and storage: O(log n) per update/query and O(n) storage.
When to recognize it: The operation has an inverse, and binary-indexed blocks decompose any prefix.
Check before applying it: Fenwick trees are specialized; arbitrary range minimum with updates lacks the same subtraction trick.
Change one rule
Need range additions and point queries.
See what changes
Store boundary changes in a Fenwick tree; a point value is their prefix sum.
Connect
prefix sums: Dynamic updates replace one frozen prefix table.
Coordinate compression: keep the order: Compress sparse ordered keys before indexing them.
Segment tree: combine range summaries: Use a segment tree for richer associative summaries.