Sparse table: frozen overlapping ranges
Picture
For many minimum queries on one frozen array, precompute answers for blocks of lengths 1,2,4,8.
Predict
Why can two overlapping blocks answer range minimum?
Walk through the small example
Minimum is idempotent. Power-of-two summaries plus an idempotent operation let two overlapping blocks cover any range.
Mental model and complete Python solution
Precompute every power-of-two window. For a query, choose the largest block that fits and place one copy at each end. Idempotence makes the overlap harmless.
What the function promises: Build on a nonempty comparable list and answer inclusive minimum queries.
class SparseMin:
def __init__(self, values):
if not values: raise ValueError("Nonempty input")
self.table = [list(values)]
length = 2
while length <= len(values):
half = length // 2
previous = self.table[-1]
self.table.append([min(previous[i], previous[i+half])
for i in range(len(values)-length+1)])
length *= 2
def query(self, left, right):
power = (right-left+1).bit_length()-1
width = 1 << power
return min(self.table[power][left], self.table[power][right-width+1])
rmq = SparseMin([5,2,7,1,3])
assert rmq.query(1,4) == 1
assert rmq.query(0,2) == 2
Work and storage: O(n log n) build time/space and O(1) range-minimum query.
When to recognize it: Power-of-two summaries plus an idempotent operation let two overlapping blocks cover any range.
Check before applying it: Updates require rebuilding, and overlapping blocks do not work for ordinary sum.
Change one rule
Point updates are frequent.
See what changes
Use a segment tree for O(log n) updates and queries.
Connect
Segment tree: combine range summaries: Trade update support for faster static queries.
Binary search: find a boundary: Bit lengths identify the largest fitting power of two.