Overview
A segment tree is a data structure that performs queries and updates over a range of array elements efficiently, in O(log n) time. Each node covers a range of the array and stores a summary of it, such as a minimum. The first worked problem is LIS, which pairs coordinate compression with a tree that tracks the best length ending at each element. The second is the range minimum query, answered from the same tree. Lazy propagation keeps a pending update at the nodes that cover a range exactly. That takes a range update from O(n log n) down to O(log n). On the sample array, updating [1, 6] touches only the nodes [1, 4] and [5, 6].
Basic Problems Using a Segment Tree
Problem 1: Longest Increasing Subsequence (LIS)
- Description: Find the longest strictly increasing subsequence in a sequence of numbers
- Method:
- Use coordinate compression to map the values in the array to a smaller range while preserving their relative order
- Use a segment tree to store and query the length of the longest increasing subsequence ending at each element
- Update and query the segment tree to find the maximum value over the relevant ranges, and from that compute the LIS
Problem 2: Range Minimum Query
- Description: Given an array A, answer queries for the minimum value over the range [l, r]
- Method:
- Build a segment tree that maintains the minimum value over ranges
- Answer the minimum query over [l, r] efficiently
Lazy Propagation
The Problem
When you need to update a range of elements in the array (rather than a single element), updating each element individually can lead to a high complexity of O(n log n).
The Idea
- Instead of updating every element, update only the nodes that cover the largest ranges in the segment tree (the nodes closest to the root) whose union is exactly the range to be updated
- Store a value at those nodes, called the lazy update value, marking that every node within this range must eventually be updated by the corresponding value
- The child nodes are brought up to date only when really necessary (during a query or when the actual value is needed)
Implementation
- Each node in the segment tree stores an extra
lazyvalue recording a pending update - To update a range, only the
lazyvalues at the corresponding nodes are updated, without immediately updating the actual values - On a query, or when the actual value is needed, propagate the
lazyvalue down to the child nodes and update the actual values
Benefits
- Reduces the complexity of range update operations from O(n log n) to O(log n)
- Optimizes performance for problems with many range update queries
Illustrated Example
With array A = [9, 2, 6, 3, 1, 5, 7], when the range [1, 6] must be updated:
- Instead of descending to update all nodes containing elements of the range [1, 6]
- Only the two largest nodes, [1, 4] and [5, 6], are updated (their union is exactly the range [1, 6])
- The child nodes are updated when necessary
References
See also: Persistent Segment Tree · Data Structures Overview · Learning Resources