Articles
Segment Tree Interview Questions: Updates, Range Queries, and Lazy Propagation
Prepare for segment tree interviews with range queries, point and range updates, lazy propagation, neutral elements, proofs, and tests.
Segment tree interview questions test whether you can summarize ranges under updates. The structure works when adjacent segment summaries combine associatively: sums, minima, maxima, greatest common divisors, or richer structs such as maximum-subarray metadata. A query decomposes its target range into disjoint tree nodes and combines them.
CP-Algorithms provides technical documentation for segment-tree construction, point updates, range queries, and lazy propagation. The key interview step is to define the stored summary and identity before coding. Lazy propagation is not a magic performance flag; it requires a pending update that can transform a whole node summary without visiting every leaf and compose correctly with later updates.
Segment Tree Interview: Quick Answer
For n values, an iterative tree stores leaves at positions size..size+n-1, where size is a power of two, and parents combine children. A point update replaces one leaf and recomputes ancestors in O(log n). A half-open query [l,r) uses left and right accumulators, taking nodes that exactly cover the remaining range, also in O(log n) for standard aggregates.
Use lazy propagation when range updates interleave with queries. For range-add/range-sum, applying delta to a node covering length len increases its sum by delta*len and accumulates the pending add tag. Before descending, push the tag to both children and clear it. For assignment plus addition, tag composition order matters and needs a richer representation.
Start with Combine and Identity
Sum uses combine a+b and identity 0. Minimum uses min and positive infinity, not zero when values may be positive. Maximum uses negative infinity. Associativity lets the tree regroup elements without changing the result; commutativity is not required. For string concatenation or matrix multiplication, left-to-right accumulator order must be preserved.
Define the empty-range result as identity if the API permits empty ranges. Validate 0 <= l <= r <= n. If the tree is empty, point updates are invalid and range query [0,0) can return identity. These contracts prevent sentinels from leaking into legitimate answers.
Implement Point Updates and Half-Open Queries
class SumTree:
def __init__(self, values):
n = len(values); size = 1
while size < n: size *= 2
self.n, self.size = n, size
self.tree = [0] * (2 * size)
self.tree[size:size+n] = values
for i in range(size-1, 0, -1):
self.tree[i] = self.tree[2*i] + self.tree[2*i+1]
def set(self, i, value):
if not 0 <= i < self.n: raise IndexError(i)
p = self.size + i; self.tree[p] = value
while p > 1:
p //= 2
self.tree[p] = self.tree[2*p] + self.tree[2*p+1]
def query(self, l, r):
if not 0 <= l <= r <= self.n: raise IndexError
l += self.size; r += self.size; left = right = 0
while l < r:
if l & 1: left += self.tree[l]; l += 1
if r & 1: r -= 1; right = self.tree[r] + right
l //= 2; r //= 2
return left + right
Separate left and right accumulators preserves order for noncommutative combines.
Trace a Query as Disjoint Coverage
For eight leaves and query [1,7), the iterative walk may select the single leaf 1, the segment [2,4), the segment [4,6), and leaf 6. These nodes are disjoint and their union is exactly the query. No selected node contains an outside element.
Each loop moves endpoints toward the root after consuming exposed boundary nodes. At most two nodes are selected per level, so work is logarithmic for standard segment queries. The build is O(size), which is O(n) because the next power of two is less than 2n for positive n. The allocated array is linear, though often larger than exactly 2n.
Define Lazy Range-Add Semantics
In a recursive tree, apply(node, delta, length) updates sum[node] += delta*length and lazy[node] += delta. If an update fully covers the node range, apply and stop. On partial overlap, push the pending tag to children, recurse into overlaps, then recompute the parent from children.
The multiplication by segment length is the common missing step. A node sum represents every element in its segment, so adding three to four elements adds twelve. For a minimum tree under range-add, the stored minimum increases only by delta, not delta times length. The aggregate and tag action must be designed together.
Compose Tags in the Correct Order
Add tags commute with each other: pending +a followed by +b becomes +(a+b). Assignment does not commute with addition. If a segment has pending +3 and then receives assign 5, the old add is discarded and value becomes 5. If it receives assign 5 then add 3, the result is assign 8 or a structured {assign:5, add:3} applied in that order.
Write a compose(new, old) contract meaning “apply old, then new” and test all pairs. Push uses that same function for child tags. Many lazy bugs arise because one call site reverses the order. Affine updates x→ax+b make the issue explicit: function composition is associative but not commutative.
Know What the Tree Cannot Summarize
Associativity is required; an arbitrary operation that depends on original grouping cannot be combined safely. Median does not have a fixed-size exact summary that merges like sum. Distinct count needs sets, bitsets, or approximate sketches whose size and error must be discussed. Range mode is substantially harder.
For sparse huge coordinates, use coordinate compression if all endpoints are known or a dynamic tree that creates nodes on demand. Persistent segment trees retain old roots after updates by copying the path, useful for version queries but adding memory. Segment tree beats and other advanced variants should appear only if the requested update/query algebra needs them.
Choose Fenwick or Segment Tree Deliberately
A Fenwick tree is smaller and simpler for prefix-compatible sums, counts, and related group operations. A segment tree is more flexible for arbitrary associative range summaries, left/right order, range updates, and rich node metadata. Static prefix sums win when there are no updates. A sparse table answers idempotent static queries such as minimum after preprocessing.
State operation counts. If one point update follows a million range queries, rebuilding a static prefix may still be acceptable depending on n. If range additions and range sums alternate, lazy propagation earns its complexity. Avoid building a recursive lazy template for a point-update problem.
Memory and constants matter. An iterative tree has compact loops and no recursion state; a recursive tree maps ranges naturally and extends to lazy tags. Both are O(n) space and logarithmic operations under the same algebra. Choose the version you can prove and test within the interview.
Make the Answer Reviewable
Turn the segment tree design into a small deterministic review before adding more scale. Write the initial state, five to ten timestamped inputs, every expected state transition, and the exact read result at two watermarks. Replay one input, deliver another out of order, pause one consumer, and rebuild the serving view from its durable boundary. The replay should not create an extra effect, the stale input should follow the declared version rule, and the rebuilt read should match the authoritative result through the same watermark.
Keep expected results independent of the implementation. If the same code produces both the output and the assertion, a shared assumption can hide the defect. Add one invariant check that scans all state, even if production serves a faster index. For a distributed design, say which part this fixture does not prove: it does not measure production latency, network partitions, or capacity. Load and fault tests come next, using the traffic and error budgets already stated.
Finish with an operational table: signal, healthy range, action, and user-visible consequence. Include ingestion or queue age, rejected or duplicate work, authoritative-versus-serving divergence, and tail read latency. This makes the proposal inspectable. An interviewer can now change one requirement and see exactly which state, test, and alert must change with it.
Separate what the review establishes from what it leaves open. A passing deterministic fixture proves the declared state transitions for those inputs. It does not establish performance at scale, fairness across real users, or behavior during every network failure. Add a capacity test for the estimated peak, a skew test concentrated on one key or partition, and a fault test at the acknowledgment boundary. Record versions and random seeds so failures can be replayed. When a result differs from expectation, reduce it to the smallest trace, name the violated invariant, and repair that transition before retuning capacity. This evidence-first sequence keeps correctness questions from being hidden inside infrastructure changes.
Keep the review artifact beside the implementation and date the environment that produced it. If a later optimization changes ordering, batching, numeric width, or retry behavior, rerun the same trace before accepting the new result. The invariant is the stable comparison point; the component diagram is not.
A 45-Minute Interview Structure
Spend five minutes on query/update types, bounds, mutability, and n. Define summary, combine, identity, and tag action. Use twelve minutes for a point-update tree and trace [1,7). Spend ten on lazy apply/push/recompute and eight on tag composition. Reserve six for complexity, edge cases, and differential tests. If the operation changes, redesign the algebra before editing traversal code.
Final Takeaway
A segment tree is correct because selected nodes form a disjoint cover and their summaries combine associatively with a true identity. Point updates rebuild one root path. Lazy range updates work only when a tag can transform a complete segment summary and compose in the declared order. Write those algebraic rules first, then test every range against a simple array oracle.
Sources and Further Reading
- CP-Algorithms segment tree
- CP-Algorithms Fenwick tree
- Python data model special methods
- Python array sequence operations
Documentation supports the stated system or algorithm behavior; individual question records support only their own practice contracts. Architecture recommendations and interview sequencing are editorial inference.