Segment tree visualizer
A segment tree stores the sum, minimum or maximum of every half, quarter and smaller piece of an array, so any range can be answered from a handful of pieces. Enter your array, run queries and updates, and see exactly which nodes each one visits and why.
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| Value | 5 | 8 | 6 | 3 | 2 | 7 | 2 | 6 |
Each node holds the sum of the range shown on it; its children split that range in half. Run an operation to see which nodes it visits.
How to use the visualizer
Type or paste your array and press Build tree. Choose whether nodes store the sum, minimum or maximum, and whether your exercise counts indexes from 0 or 1. Then run range queries, point updates or lazy range additions. Each operation is listed on the right; click one to see the tree as it was right after it, with the nodes it visited coloured and every step explained.
- Each node shows its range on top and its value below; the small number at its corner is its position in the tree array (root 1, children 2i and 2i + 1).
- Copy answer gives the built tree and every operation's steps as text; Copy link saves the array and all operations.
What is a segment tree?
A segment tree answers questions about ranges of an array, such as the sum or minimum of elements l to r, while still allowing the array to change. Summing the range directly takes time proportional to its length; keeping prefix sums answers in constant time but makes every update cost O(n). A segment tree makes both queries and updates O(log n).
It is a binary tree in which each node covers a range of the array and stores the answer for it. The root covers the whole array; each node's two children cover its left and right halves; the leaves are the single elements. Any range can then be assembled from O(log n) nodes whose ranges fit inside it.
Building the tree
Building is a recursion: a node covering [l, r] with l = r is a leaf holding a[l]; otherwise it splits at m = ⌊(l + r)/2⌋, builds both children and combines their values. Every node is built once, so the cost is O(n). For the array 5, 8, 6, 3, 2, 7, 2, 6 with sums, the tree is:
| Node | Range (0-based) | Sum |
|---|---|---|
| 1 | [0, 7] | 39 |
| 2 | [0, 3] | 22 |
| 3 | [4, 7] | 17 |
| 4 | [0, 1] | 13 |
| 5 | [2, 3] | 9 |
| 6 | [4, 5] | 9 |
| 7 | [6, 7] | 8 |
Nodes 8 to 15 are the leaves, one per element. With the root at index 1 and the children of node i at 2i and 2i + 1, the whole tree fits in a plain array. When n is not a power of two some indexes go unused, so implementations usually allocate 4n entries.
Range queries
A query for [l, r] starts at the root and, at each node, does one of three things. If the node's range lies entirely inside [l, r], it returns the stored value without going further. If it lies entirely outside, it returns nothing (0 for a sum, +∞ for a minimum). Otherwise it asks both children and combines their answers.
On the example array, the sum of [2, 6] is 20. The query visits 9 nodes, takes its answer from the whole nodes [2, 3], [4, 5], [6, 6], and skips 2 that lie outside. At most four nodes are visited on any level, so a query is O(log n). Across 24,024 sampled ranges of a 1,000-element array, whose tree has 11 levels, the most nodes any query visited was 39, and the average 32.8.
Point updates
Changing a[i] affects exactly the nodes whose ranges contain i: one per level, along the path from the root to the leaf. The update walks down that path, changes the leaf and recomputes each node on the way back up from its two children. That is O(log n) nodes, against O(n) for rebuilding prefix sums.
Lazy propagation
Adding a value to every element of a range one by one would cost O(n log n). With lazy propagation, a range update visits the same nodes a query would. At a node whose range lies entirely inside the update, it changes the node's value (by v times the range length for a sum, by v for a minimum or maximum) and records "+v pending" for its children instead of visiting them. The pending value is pushed one level down only when a later operation has to go below that node.
On the example array, adding 3 to [1, 6] visits 11 nodes and leaves pending additions on [2, 3] and [4, 5]. A later query for the single element [2, 2] has to go below one of those nodes, pushes 1 pending addition down on the way, and returns 9, which is 6 + 3.
Segment tree, Fenwick tree or prefix sums
| Structure | Range query | Point update | Range update | Operations |
|---|---|---|---|---|
| Plain array | O(n) | O(1) | O(n) | Any |
| Prefix sums | O(1) | O(n) | O(n) | Invertible, such as sum |
| Fenwick tree | O(log n) | O(log n) | O(log n) for sums, with a second tree | Invertible for ranges |
| Segment tree | O(log n) | O(log n) | O(log n) with lazy propagation | Any associative operation |
A Fenwick tree, also called a binary indexed tree, is shorter to write and uses n entries instead of up to 4n, but it answers prefix queries; a range is the difference of two prefixes, which works for sums and not for minimum or maximum. When the array never changes, prefix sums (or a sparse table for minimum) are simpler still.
Conventions that change the answer
- 0-based or 1-based indexes. Competitive programming code is usually 0-based; many textbooks number elements from 1. The switch above changes how ranges are read and shown, not the tree.
- Node numbering. With the root at 1, children are 2i and 2i + 1; with the root at 0, they are 2i + 1 and 2i + 2.
- Where the split falls. Splitting [l, r] at ⌊(l + r)/2⌋ gives the left child the extra element when the length is odd, as here. Iterative bottom-up implementations lay the tree out differently and visit different nodes, though they return the same answers.
- Inclusive or half-open ranges. This page uses [l, r] with both ends included; some code uses [l, r).
Segment tree questions and answers
What is the time complexity of a segment tree?
Building takes O(n). A range query and a point update take O(log n), and so does a range update with lazy propagation. The tree has 2n − 1 nodes, usually stored in an array of 4n entries.
How many nodes does a segment tree query visit?
At most four on each level, so O(log n). In this page's test, every sampled range of a 1,000-element array (24,024 queries) visited at most 39 nodes, 32.8 on average, in a tree 11 levels deep.
Why is the segment tree array size 4n?
When n is not a power of two the tree is not perfectly balanced, and with the root at index 1 and children at 2i and 2i + 1 some indexes in between go unused. 4n is a simple bound that is always enough; the tree itself has only 2n − 1 nodes.
What is lazy propagation?
A way to update a whole range in O(log n). Instead of changing every element, the update stops at nodes whose range lies entirely inside it, changes their value and records a pending change for their children. The pending change is pushed down only when a later operation needs to go below that node.
Segment tree or Fenwick tree?
A Fenwick (binary indexed) tree is shorter and uses less memory, but it answers prefix queries, and a range is found by subtracting two prefixes, which works for sums but not for minimum or maximum. A segment tree handles any associative operation and range updates, at the cost of more code.