Segment Tree
This page provides links to solutions for problems that use the Fenwick Tree data structure.
Overview
A Segment tree is a type of data structure that allows range operations, such as finding total, minimum, maximum, distinct value within a range, in time complexity.
Additionally, it can perform point and range updates in time as well. Despite its name, a segment tree is actually stored as an array of elements.
Build Segment Tree
Let's build a range sum segment tree for following array.
Even thought it is called a segment tree, it is stored as an array. To build a segment tree for an input array with elements, we start by creating an array of size times the size of an input array.
Since there are elements in an input array, build function will start with range . Segment tree array index will be at .
Build function splits the range in half, the left segment range becomes . Segment tree array index when it goes to left subtree becomes .
Recursively splitting the left subtree further, we get the left segment range as . Segment tree array index becomes .
Further splitting the left subtree, the segment reduces to a single point . At this point, we assign the element from the input array at index to current segment tree array index, so we assign tree[] = arr[].
After reaching the segment, we cannot split the left subtree further. The build function backtracks and splits the right subtree of the parent into two halves, resulting in a single point segment .
Since this is a single point, we assign the value from the input array at index to the current segment tree array index. Therefore, we assign tree[] = arr[].
At this point, we have completed splitting both the left and right subtree of the segment range . We then apply the sum function to combine the values from both child indexes and assign the result to the current segment tree array index. Thus we assign tree[] = tree[] + tree[] = .
After completing the recursive process described above, the segment tree will be fully built. Below are snapshots of each step.
- Java
long[] arr;
long[] tree;
public SegmentTreeSum(long[] arr) {
this.arr = arr;
this.tree = new long[4 * arr.length];
build(0, 0, arr.length - 1);
}
public void build(int treeIndex, int fromArrIndex, int toArrIndex) {
if (fromArrIndex == toArrIndex) {
tree[treeIndex] = arr[fromArrIndex];
}
else {
int mid = fromArrIndex + (toArrIndex - fromArrIndex) / 2;
build(2 * treeIndex + 1, fromArrIndex, mid);
build(2 * treeIndex + 2, mid + 1, toArrIndex);
tree[treeIndex] = tree[2 * treeIndex + 1] + tree[2 * treeIndex + 2];
}
}
Use Segment Tree
Let's use the segment tree to find the range sum of indexes in an input array.
We begin calculation of the range sum from the root node, which represent index of a segment tree array and range of an input array.
There are main conditions to consider at any given node:
-
Outside of Input Range: Return if the range at the current node falls entirely outside the input range.
-
Subset of Input Range: Return the precomputed sum from the segment tree if the range at the current node is part of input range.
-
Partially Overlaps Input Range: If range at current node partially overlaps with input range recursively calculate values from left and right subtree and return the result.
The range at current node, , partially overlaps input range