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

Segment Tree

Answer range queries and point updates in O(log n). Segment trees are the go-to structure for range sum, range min, and similar problems.

segment-treetreerange-querydivide-and-conquer

Interactive visualization

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

|
Press Build to construct the segment tree.
[0,7][0,3][4,7][0,1][2,3][4,5][6,7][0,0][1,1][2,2][3,3][4,4][5,5][6,6][7,7][0]3[1]1[2]4[3]1[4]5[5]9[6]2[7]6
Idle Visiting Contributing Updated

Family

Range queries

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

Builds on

2 topics

Read these first if you want the surrounding context.

Unlocks

4 next topics

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

Learning paths

3

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

Choose this over that

Use a segment tree only when you need its extra power

The heavier structure is worth it when the query or update model stops being prefix-friendly.

Range queries Open topic

Fenwick Tree (Binary Indexed Tree)

Choose this when: You only need dynamic sums or prefix-style aggregates and want a lighter structure.

Choose something else when: Range updates, general associative merges, or tree flattening tricks are coming next.

Current topic

Segment Tree

Choose this when: You need flexible merge operations, lazy propagation, or advanced variants like persistent or Li Chao trees.

Choose something else when: The array is static or sum-only logic is enough.

Range queries Open topic

Sparse Table

Choose this when: Queries are static, idempotent, and should be as close to instant as possible.

Choose something else when: The structure needs to handle updates.

Problem

You have an array of nn elements. You need to:

  • Query an aggregate (sum, min, max) over any subarray [L,R][L, R]
  • Update individual elements

A naive approach gives O(1)O(1) update and O(n)O(n) query, or O(n)O(n) update and O(1)O(1) query with prefix sums. A segment tree gives O(logn)O(\log n) for both.

Intuition

Divide the array into segments recursively. Each node in the tree stores the aggregate for its segment. The root covers [0,n1][0, n-1], its children cover [0,mid][0, \text{mid}] and [mid+1,n1][\text{mid}+1, n-1], and so on down to individual elements at the leaves. Any range [L,R][L, R] can be decomposed into O(logn)O(\log n) disjoint segments already stored in the tree.

Build

Construct bottom-up. Leaves hold the original array values. Each internal node merges its two children.

build(node, start, end, arr):
    if start == end:
        tree[node] ← arr[start]
        return
    mid ← (start + end) / 2
    build(2*node, start, mid, arr)
    build(2*node+1, mid+1, end, arr)
    tree[node] ← tree[2*node] + tree[2*node+1]

O(n)O(n) time — each of the 2n12n - 1 nodes is visited once.

Query

To query [L,R][L, R]: at each node covering [start,end][\text{start}, \text{end}], either the segment is fully inside [L,R][L, R] (return it), fully outside (return identity), or partially overlapping (recurse into both children and combine).

query(node, start, end, L, R):
    if R < start or end < L:       // no overlap
        return 0
    if L <= start and end <= R:     // total overlap
        return tree[node]
    mid ← (start + end) / 2        // partial overlap
    return query(2*node, start, mid, L, R)
         + query(2*node+1, mid+1, end, L, R)

At most O(logn)O(\log n) nodes are visited — two per level of the tree.

Update

To update index ii: walk from the root to the leaf, then propagate the new aggregate back up.

update(node, start, end, i, val):
    if start == end:
        tree[node] ← val
        return
    mid ← (start + end) / 2
    if i <= mid:
        update(2*node, start, mid, i, val)
    else:
        update(2*node+1, mid+1, end, i, val)
    tree[node] ← tree[2*node] + tree[2*node+1]

One root-to-leaf path → O(logn)O(\log n).

Lazy propagation

When you need range updates (add vv to every element in [L,R][L, R]), visiting every leaf is O(n)O(n). Lazy propagation defers updates: mark a node as “pending” and only push the update down to children when they’re actually queried. This keeps both range update and range query at O(logn)O(\log n). The tradeoff is implementation complexity — you maintain a separate lazy[] array and flush pending updates before any node access.

Array representation

A segment tree on nn elements is stored in a flat array of size 4n4n. Node ii has:

  • Left child: 2i2i
  • Right child: 2i+12i + 1
  • Parent: i/2\lfloor i / 2 \rfloor

The root is at index 1 (index 0 is unused). This is the same trick as a binary heap but with 1-based indexing.

Common patterns

PatternMerge operationIdentity
Range suma+ba + b00
Range minmin(a,b)\min(a, b)++\infty
Range maxmax(a,b)\max(a, b)-\infty
Range GCDgcd(a,b)\gcd(a, b)00
Count in rangea+ba + b (with predicate at leaves)00

Any associative operation works. The merge function defines what your tree computes.

Complexity

OperationTimeSpace
BuildO(n)O(n)O(4n)O(4n)
Point queryO(logn)O(\log n)
Range queryO(logn)O(\log n)
Point updateO(logn)O(\log n)
Range update (lazy)O(logn)O(\log n)O(4n)O(4n) extra

Key takeaways

  • Any associative operation works as the merge function — sum, min, max, GCD, bitwise OR. Define the merge and identity, and the tree handles the rest.
  • O(logn)O(\log n) for both query and update is the sweet spot between prefix sums (O(1)O(1) query, O(n)O(n) update) and naive arrays (O(n)O(n) query, O(1)O(1) update).
  • Lazy propagation is essential for range updates — without it, updating a range of elements is O(n)O(n). With it, both range update and query stay O(logn)O(\log n).
  • Flat array of size 4n4n with 1-based indexing — node ii has children 2i2i and 2i+12i+1. No pointers, no overhead, cache-friendly.
  • Segment trees dominate when you need both updates and queries — if the array is static, prefer a sparse table or prefix sums.

Practice problems

ProblemDifficultyKey idea
Range Sum Query - Mutable🟡 MediumDirect segment tree application for sum queries with point updates
My Calendar I🟡 MediumSegment tree or balanced BST to detect overlapping intervals
Count of Smaller Numbers After Self🔴 HardSegment tree on value space, processing array right to left
The Skyline Problem🔴 HardSweep line with segment tree or priority queue for active heights
Count of Range Sum🔴 HardSegment tree on prefix sums to count valid ranges

Relation to other topics

Fenwick tree (BIT): simpler to implement, less memory, but only supports prefix queries natively. You can do range queries with two prefix queries, but operations like range min don’t work. If all you need is range sum with point updates, a Fenwick tree is lighter.

Sparse table: O(1)O(1) range min/max queries after O(nlogn)O(n \log n) preprocessing, but the array must be static — no updates allowed.

Sqrt decomposition: O(n)O(\sqrt{n}) per query and update. Much simpler to implement. Good enough when n105n \leq 10^5 and you want fast coding time over optimal asymptotic complexity.

Build on these first

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

What this enables

Once the current idea feels natural, these are the most useful next jumps.

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.

Tree path queries

Build the full ladder from ancestor queries to heavy-light decomposition and historical segment trees.

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.