Data Structure used to efficiently store and maintain information about intervals, or segments.
- Segment tree is a binary tree
- Each node stores a value
v
for the interval[l,r]
- Root node represents the full interval
[0,n-1]
- If node
v
represents[l,r]
, its left child represents[l,m]
and its right child[m+1,r]
wherem=(l+r)/2
- Leaves represent unit-intervals
[t,t]
- segment tree has height
H = floor(log2(2n-1))
- Round
n
up to power of2
(fill tail with0
) for complete binary tree - Store node values in array of length
2n
- Begin with storing root node at index
1
(0
th element is unused) - Children of node
i
are stored at2i
and2i+1
- Calculate layer
l
of nodei
in tree asl = floor(log2 i)
- Calculate
[l,r]
bounds of nodei
as[(i - (1 << l)) << (H - l), (((i - (1 << l)) + 1) << (H - l)) - 1]
(Note: That always calculating bounds on demand may decrease performance instead of storing bounds additionally to node values. Depends on cache locality.)
Recursively build the segment tree for input a
.
Start at root node and as long as we're not at a leaf recursively call build on left, right child.
When at leaf store input value from a
and return it.
On return of left and right child store the sum of the two values and return it.
Return the sum of the values stored in the interval [l,r]
- Check if we're completely outside the interval. If so return
0
. - Propagate
- Check if we're fully inside the interval. If so return node value.
- Return the sum of the left child plus the sum of the right child (Note: For Segment Trees of different kind - e.g. storing maximum/minimum of interval - we would choose another binary operator than Addition.)
Additionally to node value store lazy value representing not yet propagated additional values for an interval.
- Add lazy value
z
to nodei
at[l,r]
: add value(r-l+1)*z
- If not at leaf add lazy value to child nodes
- Reset lazy value for node
i
to0
Add value to all nodes in interval [l,r]
.
- Check if completely outside of interval. If so return.
- Check if we're fully inside the interval. If so add value as lazy value, propagate and return.
- If we're not at leaf. Recursively call range_add on children. Update node value as left child value plus right child value.