Skip to main content
Back to the DSA atlas
Range queries Data structure Advanced

Sparse Table

Answer static range minima, maxima, or gcd queries in O(1) after O(n log n) preprocessing. Sparse tables are pure precomputation power.

sparse-tablerange-queryidempotentrare

Interactive visualization

Use the controls to connect the idea to concrete operations before diving into the full write-up.

Array

idx 0

7

idx 1

2

idx 2

3

idx 3

0

idx 4

5

idx 5

10

idx 6

3

idx 7

12

Sparse table layers

2^0 block length = 1

[0, 0]

7

[1, 1]

2

[2, 2]

3

[3, 3]

0

[4, 4]

5

[5, 5]

10

[6, 6]

3

[7, 7]

12

2^1 block length = 2

[0, 1]

2

[1, 2]

2

[2, 3]

0

[3, 4]

0

[4, 5]

5

[5, 6]

3

[6, 7]

3

2^2 block length = 4

[0, 3]

0

[1, 4]

0

[2, 5]

0

[3, 6]

0

[4, 7]

3

2^3 block length = 8

[0, 7]

0

Static queries, no updates

Use two overlapping blocks of length 4: [1, 4] and [3, 6]. This works because min is idempotent.

Answer for RMQ[1, 6]: 0

Family

Range queries

Static and dynamic range aggregates via indexed trees, segment trees, and precomputed tables.

Builds on

1 topic

Read these first if you want the surrounding context.

Unlocks

0 next topics

Use these follow-ups when you want to apply the current idea in a richer setting.

Learning paths

1

This topic appears in curated progressions so you can keep moving without guessing the next step.

Choose this over that

Static queries are where sparse tables shine

The price of `O(1)` query time is that the data cannot change afterward.

Range queries Open topic

Prefix Sum

Choose this when: The problem is only static range sums and the simplest structure wins.

Choose something else when: You need minima, maxima, or other idempotent range queries beyond sums.

Current topic

Sparse Table

Choose this when: The array is immutable and you want very fast static range queries.

Choose something else when: Any update must be supported.

Range queries Open topic

Segment Tree

Choose this when: The data changes or the query pattern needs dynamic structure.

Choose something else when: The workload is entirely read-only.

Problem

You have a fixed array and need to answer lots of range queries like:

  • minimum on [L,R][L, R]
  • maximum on [L,R][L, R]
  • gcd on [L,R][L, R]

There are no updates. Since the array never changes, you should spend preprocessing time to make queries almost free.

Intuition

Precompute answers for every range whose length is a power of two:

  • length 1
  • length 2
  • length 4
  • length 8

Let st[k][i] store the answer for the interval starting at i with length 2k2^k.

Then a large query can be answered with just two overlapping power-of-two blocks.

Build

st[0][i] <- arr[i]

for k in 1..LOG:
    for i in 0..n - 2^k:
        st[k][i] <- merge(st[k-1][i], st[k-1][i + 2^(k-1)])

For range minimum query, merge is just min.

Query for RMQ

For a query [L,R][L, R]:

  • let len = R - L + 1
  • let k = floor(log2(len))
  • answer with
min(st[k][L],st[k][R2k+1])\min(st[k][L], st[k][R - 2^k + 1])

Those two blocks cover the whole interval. They may overlap, but that is okay because min, max, and gcd are idempotent.

The idempotent restriction

Sparse tables are amazing only when overlap is harmless.

Good operations:

  • min
  • max
  • gcd
  • bitwise and/or

Bad operations:

  • sum
  • xor counts
  • anything where double-counting changes the answer

If overlap breaks the merge, you need a segment tree, Fenwick tree, or another structure instead.

Why it feels like binary lifting

Sparse tables and binary lifting share the same core idea:

precompute answers for jumps of size 2k2^k

Sparse tables jump over interval lengths. Binary lifting jumps over ancestors. Same doubling pattern, different domain.

Complexity

OperationTimeSpace
BuildO(nlogn)O(n \log n)O(nlogn)O(n \log n)
QueryO(1)O(1)O(nlogn)O(n \log n)

Key takeaways

  • Sparse tables are unbeatable for static idempotent range queries
  • The structure is just doubling: every level merges two blocks from the previous level
  • Two overlapping power-of-two blocks are enough for RMQ in O(1)O(1)
  • Do not use a sparse table if the operation cannot tolerate overlap
  • Binary lifting is the tree analogue of the same precompute-by-powers-of-two idea

Practice problems

ProblemDifficultyKey idea
Minimum Absolute Difference Queries🔴 HardStatic range information, often with heavy preprocessing
K-th Ancestor of a Tree Node🟡 MediumSame doubling idea as sparse tables, but on ancestors
Static RMQ🟡 MediumRange minimum query benchmark

Relation to other topics

  • Fenwick tree is dynamic but only naturally handles prefix-like merges
  • Segment tree handles updates and general merges, but queries stay O(logn)O(\log n)
  • Binary lifting uses the same doubling table idea on rooted trees rather than arrays

Build on these first

These topics supply the mental model or underlying structure that this page assumes.

Related directions

These topics live nearby conceptually, even if they are not direct prerequisites.

More from Range queries

Stay in the same family when you want parallel variations of the same mental model.

Paths that include this topic

Follow one of these sequences if you want a guided next step instead of open-ended browsing.

Range-query toolkit

Start with static prefix tricks, then move into offline, persistent, dynamic, and precomputed range-query structures.

From the blog

Pair the atlas with recent writing from the rest of the site when you want a broader engineering perspective alongside the topic graph.