~/problems / Range queries / Segment tree (+ lazy propagation)

Basics: build and update a bottom-up segment tree

easy basics ~10 min

The short way to write a segment tree is a flat list tree of length 2n:

  • the leaves are tree[n .. 2n-1], a copy of nums;
  • every internal node i (from n - 1 down to 1) stores tree[2i] + tree[2i + 1], the sum of its two children;
  • tree[0] is unused and stays 0. tree[1] ends up holding the sum of everything.

Write the two operations everything else is built on:

  • build(nums) -> list[int]: return that list of length 2 * len(nums).
  • update(tree, i, value) -> None: set position i (0-based) of the original array to value, in place, and fix every ancestor so the invariant holds again. Only touch the O(log n) nodes on the way up; don't rebuild.
tree = build([5, 3, 2, 7])
# [0, 17, 8, 9, 5, 3, 2, 7]
#     ^root ^  ^  leaves...
update(tree, 1, 10)
# tree == [0, 24, 15, 9, 5, 10, 2, 7]

Constraints: 1 <= len(nums) <= 10**5, values may be negative. n doesn't have to be a power of two; the same formulas still work.

Show hint

node i's parent is i // 2, so after writing the leaf at n + i, walk i //= 2 up to the root, recomputing each node from its two children.

Topic: Segment tree (+ lazy propagation). Any associative range query with point or range updates in O(log n).

Read the visual guide
0:00
Ctrl ' run · Ctrl ↵ submit
esc