Quant Memo
Core

Sparse Tables and Range Queries

A precomputation trick that answers 'what's the min (or max) over any range of an array' in constant time after one setup pass — handy for fast rolling-window stats on static data.

Given a fixed array — say, a day's minute bars of price — you often need to repeatedly answer "what was the minimum price between minute ii and minute jj?" for many different ranges. A naive scan over each query range takes time proportional to the range length every time; if you're firing thousands of such queries, that adds up fast.

A sparse table precomputes, once, the minimum (or maximum) over every range whose length is a power of two, starting at every index. Table entry sparse[k][i]\mathrm{sparse}[k][i] stores the minimum of the 2k2^k elements starting at index ii, built up from smaller powers: sparse[k][i]=min(sparse[k1][i], sparse[k1][i+2k1])\mathrm{sparse}[k][i] = \min(\mathrm{sparse}[k-1][i],\ \mathrm{sparse}[k-1][i + 2^{k-1}]). This precomputation takes O(nlogn)O(n \log n) time and space. Answering any range-minimum query afterward takes O(1)O(1): pick the largest power of two, 2k2^k, that fits inside the query range, and take the min of the two (possibly overlapping) precomputed blocks of that size covering the range — since min is idempotent, overlapping is harmless.

The catch is that this only works for static data and an idempotent operation like min, max, or gcd; it does not support updates after the table is built, and it doesn't work for sum (which double-counts the overlap). For that use case a segment tree, which supports updates, is the right tool instead.

A sparse table trades O(nlogn)O(n \log n) one-time precomputation for O(1)O(1) range min/max queries on data that never changes — it works because overlapping power-of-two blocks can be combined safely under min/max, but not under sum, and it can't handle updates the way a segment tree can.

Practice in interviews

Further reading

  • CP-Algorithms, Sparse Table
ShareTwitterLinkedIn