COMPUTER ENGINEER

← BlogDATA STRUCTURES / ALGORITHMSPython example pack ↓

Trees and indexes · 24 / 53

Persistent structures and augmentation

Understand → trace → implement → justify

1 min reading · allow extra time for practice

Persistent structures preserve old versions after updates. Path copying duplicates only the changed root-to-leaf path and shares untouched immutable subtrees. Partial persistence reads old versions; full persistence permits branching updates from them.

A persistent segment-tree point update creates O(log n) nodes. Root references represent snapshots; comparing versions enables historical range queries. Track version lifetimes, since immutability does not eliminate memory growth.

Augmentation stores local metadata such as size, sum or maximum interval endpoint. Interval trees use maximum endpoints to prune overlap searches. O(1) recomputation from children keeps rotations cheap. Mutating a shared old node destroys historical correctness.

A worked trace

Updating one item in an eight-leaf segment tree copies four path nodes including the root and shares other branches.

Cost and assumptions

Point update O(log n) time/new space; q versions use O(n+q log n) total space.

Executable example

Run with Python 3. Assertions check a small example; they do not constitute a general correctness proof. Some advanced examples are explicitly small models or reference oracles, not full production implementations.

Python 3
# Minimal immutable node; unchanged children may be shared.
from dataclasses import dataclass
@dataclass(frozen=True)
class Tree:
    total: int
    left: object = None
    right: object = None
old = Tree(3, Tree(1), Tree(2))
new = Tree(7, Tree(5), old.right)
assert old.total == 3 and new.right is old.right

TEST YOUR UNDERSTANDING

Your turn

Why is mutating an old version’s shared right child dangerous?

Reveal the reasoning

The new version uses the same node, so both change. Use immutable nodes or genuine copy-on-write.

Take it further

  1. Write down the input contract and the invariant before changing the example.
  2. Add empty, boundary, duplicate and adversarial cases where they are relevant. Compare with a simple oracle.
  3. Derive the cost under the stated model; measure several input sizes and explain discrepancies.

Primary reading & lecture notes

Original explanations in this course; these references provide proofs and further reading. Source links may cover the broader module.

MIT 6.046J · Design and Analysis ↗
Solve the exercise before moving on.