Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Coding Interview Patterns  Module 30 – Range queries: Fenwick and segment trees

Sparse tables: range minimum and LCA in O(1)

The lowest temperature of any span of a finished season, and the deepest folder that holds two files: the problems, examples, brute forces and the signal.

  • Advanced
  • 45 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0, quickjs 0.32.0, Java 25, Clang 21.0.0 and Go 1.27.1
  • By MySmartCoPilot
Free intro, Pro: 10 of 45 minutes free
Free: Two problems on data that never changes · The brute force: scan the span, walk up the tree. With a pass: the other 14 sections and 3 interview answers, about 35 minutes.

What you will learn

  • Build a sparse table in O(n log n) and answer a range minimum in O(1)
  • Prove that two overlapping blocks give the right minimum, and show why a sum breaks
  • Convert lowest-common-ancestor questions into range minimums over an Euler tour
  • Build the Euler tour without recursion, for chains of 100,000 folders and more
  • Compare the Euler tour with binary lifting and with walking up, measured on two shapes of tree

Before you start

What you’ll learn · Before you start

What you will learn

  • Build a sparse table in O(n log n) and answer a range minimum in O(1)
  • Prove that two overlapping blocks give the right minimum, and show why a sum breaks
  • Convert lowest-common-ancestor questions into range minimums over an Euler tour
  • Build the Euler tour without recursion, for chains of 100,000 folders and more
  • Compare the Euler tour with binary lifting and with walking up, measured on two shapes of tree

Before you start

On this page

A sparse table answers the minimum of any range of fixed data in O(1): it stores the minimum of every block whose length is a power of two, and any range is covered by two such blocks that may overlap, which a minimum allows. The same table answers lowest-common-ancestor questions on a fixed tree in O(1) each, through an Euler tour of the tree. This lesson works both on two original problems: the lowest temperature of a finished season, and the deepest folder that holds two files.

Two problems on data that never changes

Problem A: the coldest span of a season. A weather station’s season is over: lows[d] is the lowest temperature of day d, in whole degrees, possibly negative. Answer many questions “what was the lowest temperature from day l to day r?”. With lows = [4, 2, 7, -1, 3, -1, 6, 5], days 0 to 7 give −1, days 0 to 2 give 2, days 4 to 7 give −1 and days 6 and 7 give 5.

Problem B: the deepest common folder. A shared drive has n folders; parent[v] holds folder v, and the root has −1. For a pair of folders, find the deepest folder that contains both, their lowest common ancestor (LCA), and the number of cd steps from one to the other. In the tree of the diagram below, drafts and specs meet in docs, 3 steps apart; ui and tests in src; drafts and ui only in the root; and app contains ui itself.

Limits for both: up to 200,000 values or folders and 200,000 questions.

The brute force: scan the span, walk up the tree

For A, scan the days of each span. For B, walk the deeper folder up to the other’s depth, then both up together until they meet:

Both brute forces, with the steps counted on two shapes of tree Python · brute/brute_force.py
"""Both problems the slow way, with the work counted: scan every span of days, and walk up from both folders."""
import random

lows = [4, 2, 7, -1, 3, -1, 6, 5]
spans = [(0, 7), (0, 2), (4, 7), (6, 7)]
print("A: daily lows", lows)
print("   lowest of each span:", [min(lows[a : b + 1]) for a, b in spans])

parent = [-1, 0, 0, 1, 1, 2, 2, 5, 3]  # 0 is the root folder
names = ["/", "docs", "src", "notes", "specs", "app", "tests", "ui", "drafts"]


def depth_of(parent):
    depth = [0] * len(parent)
    for v in range(len(parent)):  # here every parent has a smaller number than its child
        if parent[v] >= 0:
            depth[v] = depth[parent[v]] + 1
    return depth


def walk_up(parent, depth, a, b):
    steps = 0
    while depth[a] > depth[b]:
        a, steps = parent[a], steps + 1
    while depth[b] > depth[a]:
        b, steps = parent[b], steps + 1
    while a != b:
        a, b, steps = parent[a], parent[b], steps + 2
    return a, steps


depth = depth_of(parent)
print("B: deepest common folder of each pair")
for a, b in [(8, 4), (7, 6), (8, 7), (5, 7), (4, 4)]:
    print(f"   {names[a]} and {names[b]}: {names[walk_up(parent, depth, a, b)[0]]}")

rng = random.Random(6)
for shape, n in (("random tree", 20_000), ("chain", 3_000)):
    parent = [-1] + [rng.randrange(v) if shape == "random tree" else v - 1 for v in range(1, n)]
    depth = depth_of(parent)
    steps = sum(walk_up(parent, depth, rng.randrange(n), rng.randrange(n))[1] for _ in range(n))
    print(f"{shape} of {n:,} folders, {n:,} questions: {steps:,} steps up, {steps / n:,.1f} a question")
print("a chain of 200,000 folders: about 200,000 / 3 = 66,667 steps a question, so about 1.3e+10 for 200,000"
      " questions (estimated)")

Output

A: daily lows [4, 2, 7, -1, 3, -1, 6, 5]
   lowest of each span: [-1, 2, -1, 5]
B: deepest common folder of each pair
   drafts and specs: docs
   ui and tests: src
   drafts and ui: /
   app and ui: app
   specs and specs: specs
random tree of 20,000 folders, 20,000 questions: 351,966 steps up, 17.6 a question
chain of 3,000 folders, 3,000 questions: 2,990,113 steps up, 996.7 a question
a chain of 200,000 folders: about 200,000 / 3 = 66,667 steps a question, so about 1.3e+10 for 200,000 questions (estimated)

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 brute_force.py

A scan of a random span reads about a third of the season, about 66,000 days at the limit, for each question. Walking up costs the depth of the tree: 17.6 steps a question on a random tree, but about n / 3 on a chain, where every folder holds the next. A chain of 200,000 folders needs about 1.3 × 10¹⁰ steps for 200,000 questions.

What to notice

Nothing changes after the data is read, so slow preparation is fine if every question becomes cheap. For A, a minimum does not mind counting a day twice, so two overlapping blocks of a power-of-two length can cover any span. For B, write down the folders in the order a depth-first walk visits them, each time it is at one: between the first visits of two folders, the walk stays inside their LCA’s subtree and passes the LCA itself, so the shallowest folder there is the answer, which is problem A on the tour’s depths.

A tree of 9 folders and its 17-entry Euler tour; between the first visits of folders 8 and 4 the shallowest is folder 1.A folder tree and its Euler tourThe tour writes a folder each time the walk is at it0/1docs2src3notes4specs5app6tests8drafts7uiTour positions 0 to 16: folder, then depth0123456789101112131415160011328332114211002152735221622100Folder 8 (drafts) is first visited at position 3,folder 4 (specs) at position 6. The shallowest folder ofpositions 3 to 6 is folder 1 (docs), at depth 1:the deepest folder that holds both.

The deepest common folder of drafts and specs, read off the tour

Text description of the diagram

The tree has 9 folders. Folder 0 (/) holds folders 1 (docs) and 2 (src). Docs holds 3 (notes) and 4 (specs); src holds 5 (app) and 6 (tests). Notes holds 8 (drafts) and app holds 7 (ui).

A depth-first walk that writes a folder down each time it is at that folder gives the tour 0, 1, 3, 8, 3, 1, 4, 1, 0, 2, 5, 7, 5, 2, 6, 2, 0, positions 0 to 16. Under each entry is its depth: 0, 1, 2, 3, 2, 1, 2, 1, 0, 1, 2, 3, 2, 1, 2, 1, 0.

Folder 8 is first visited at position 3 and folder 4 at position 6. Positions 3 to 6 are shaded: folders 8, 3, 1 and 4, at depths 3, 2, 1 and 2. The shallowest of them is folder 1 at depth 1, outlined, and folder 1, docs, is the deepest folder that holds both drafts and specs.

The main alternative for problem B is binary lifting, which stores each folder’s ancestors 1, 2, 4 and more levels up and answers a question in O(log n) steps.

The sparse table, step by step Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • Why two overlapping blocks give the right minimum: the proof
  • The cost, with numbers
  • LCA by Euler tour, step by step
    • Why the shallowest folder between the first visits is the LCA: the proof
    • A dry run on the folder tree
  • The code in five languages
    • Checked against walking up, on 3,000 random trees
  • Binary lifting instead, measured
  • Seven bugs reproduced
  • Variants
  • Edge cases
  • Follow-up questions, answered
  • Exercise
    • The deepest common folder of many pairs
  • A practice set with sample answers
  • Check yourself
  • Interview questions
    • What is the Euler tour of a tree, and how does it turn a lowest-common-ancestor question into a range minimum?
    • A log of 10⁷ 32-bit readings is frozen at midnight. Overnight, analysts run 10⁸ questions of three kinds over ranges: the maximum, the gcd and the sum. The machine has 1 GB. Which structures do you build, and how much memory and time do they take?
    • In a 45-minute round you must answer 10⁶ lowest-common-ancestor questions on a fixed tree of 10⁵ nodes, given as a parent array. Which method do you write, the Euler tour with a sparse table, binary lifting or walking up, and how do you defend the choice?
    • Depots form a tree of 10⁵ roads. Three couriers at depots a, b and c want to meet at the depot that makes their total travel smallest. Answer 10⁵ such questions, each with the meeting depot and the total distance. How, and why is your meeting depot right?
  • Key takeaways

7 runnable examples (C++, Go, Java, JavaScript, Python, Python (check.py), Python (lifting.py)) · 1 exercise with sample tests · 3 interview answers · about 25 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.