Info & Theory
A segment tree is a binary tree built over the indices of an array, where each node covers a contiguous range. Leaves cover single elements; each internal node stores an aggregate (sum or minimum) of its range, computed from its two children.
O(n) build
Building bottom-up (or via a recursive divide-and-conquer)
combines n leaves into
~2n total nodes, doing O(1) work
per node — O(n) overall.
O(log n) range query
A query [L,R] recurses into a node's range: if
it's fully outside [L,R], skip; if fully
inside, use the node's precomputed aggregate directly; if
partially overlapping, recurse into both children. At most
O(log n) nodes are ever fully combined, because
the query range decomposes into at most two "chains" of
canonical sub-ranges per tree level.
O(log n) point update
Updating one array element only invalidates the
O(log n) ancestors on the path from that leaf
to the root; each is recomputed from its two children on
the way back up.
Why not just prefix sums?
Prefix sums answer range-sum in O(1) but need
O(n) to update a single element, and cannot
support range-minimum at all (minimum has no inverse
operation). A segment tree trades a little query speed for
fast updates and support for any associative combiner.
Beyond this simulation
Lazy propagation extends segment trees to support
O(log n) range updates (not just point
updates) by deferring pending updates on subtrees until they
are actually visited.