
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Segment Tree Sum Query
Segment Tree
A segment tree is a tree data structure used for storing intervals and segments. It is a static structure, i.e. it cannot be modified once it is built. Segment trees are used to handle range queries on an array or a similar linear data structure.
In a segment tree, we divide an input array into segments and precompute the values for these segments. Each node in a segment tree depicts an interval or segment of the array. The root node represents the entire array and each child node represents the segments formed by dividing the parent node. This division leads to representing the leaf nodes as individual elements of the array.
Segment Tree for Range of Sum queries
Original Array: [7, 1, 2, 3, 6, 5, 0, 4] Segment Tree: 38 / \ 13 25 / \ / \ 8 5 11 4 / \ / \ / \ / \ 7 1 2 3 6 5 0 4
Segment Tree has a complexity of O(logN) for each range query and update operation.
Range Sum Query RSQ is a common problem where for a given array, we need to find the sum of all elements in a range specified. Segment Tree is the most efficient data structure used for the problem.
Problem Statement
Given an array of integers arr[] containing N elements along with start and end index. The task is to find the sum of all the elements in the range [start, end].
Sample Example 1
Input
N = 8 arr[] = {1, 7, 8, 9, 5, 2, 3, 4} start = 2 end = 6
Output
27
Explanation
Array within the specified range is: {8, 9, 5, 2, 3} In the given range, the sum of elements = 8 + 9 + 5 + 2 + 3 = 27.
Sample Example 2
Input
N = 3 arr[] = {1, 3, 2} start = 1 end = 1
Output
3
Explanation
Array within the specified range is: {3} In the given range, the sum of elements = 3.
Solution Approach
The Range Sum Query problem can be solved by following the following steps
Construct a segment tree for the input array.
-
Recursively find the segment of the tree contained in the query. Each segment can be categorised as one of the following
Complete Overlap Current segment is completely within the query range.
No Overlap Current segment is completely outside the query range.
Partial Overlap Current segment partially covers the query range.
Pseudocode to Construct Segment Tree
function segmentTreeUtil(arr, seg_start, seg_end, tree, curr): if seg_start == seg_end: tree[curr] = arr[seg_start] return arr[seg_start] mid = getMid(seg_start, seg_end) tree[curr] = segmentTreeUtil(arr, seg_start, mid, tree, curr * 2 + 1) + segmentTreeUtil(arr, mid + 1, seg_end, tree, curr * 2 + 2) return tree[curr] function segmentTree(arr, n): x = ceil(log2(n)) max_size = 2 * pow(2, x) - 1 tree = new int[max_size] segmentTreeUtil(arr, 0, n - 1, tree, 0) return tree
Pseudocode for RSQ
function RSQUtil(tree, seg_start, seg_end, start, end, curr): if start <= seg_start AND end >= seg_end: return tree[curr] if seg_end < start OR seg_start > end: return 0 mid = getMid(seg_start, seg_end) return RSQUtil(tree, seg_start, mid, start, end, 2 * curr + 1) + RSQUtil(tree, mid + 1, seg_end, start, end, 2 * curr + 2) function RSQ(tree, n, start, end): if start < 0 OR end > n - 1 OR start > end: print "Query Range Invalid" return -1 return RSQUtil(tree, 0, n - 1, start, end, 0)
Example: C++ Implementation
The following code constructs a segment tree to solve the RSQ problem.
#include <bits/stdc++.h> using namespace std; int getMid(int x, int y){ return x + (y - x) / 2; } // Recursive function used to find the sum of elements in the query range int RSQUtil(int *tree, int seg_start, int seg_end, int start, int end, int curr){ // Complete Overlap if (start <= seg_start && end >= seg_end) return tree[curr]; // No Overlap if (seg_end < start || seg_start > end) return 0; // Partial Overlap int mid = getMid(seg_start, seg_end); return RSQUtil(tree, seg_start, mid, start, end, 2 * curr + 1) + RSQUtil(tree, mid + 1, seg_end, start, end, 2 * curr + 2); } // Calculates RSQ by calling RSQUtil( int RSQ(int *tree, int n, int start, int end){ if (start < 0 || end > n - 1 || start > end){ cout << "Query Range Invalid"; return -1; } return RSQUtil(tree, 0, n - 1, start, end, 0); } // Creates Segment Tree for input array int segmentTreeUtil(int arr[], int seg_start, int seg_end, int *tree, int curr){ // Base Case of only one element in array if (seg_start == seg_end){ tree[curr] = arr[seg_start]; return arr[seg_start]; } // Dividing array into segments int mid = getMid(seg_start, seg_end); tree[curr] = segmentTreeUtil(arr, seg_start, mid, tree, curr * 2 + 1) + segmentTreeUtil(arr, mid + 1, seg_end, tree, curr * 2 + 2); return tree[curr]; } // Creates Segment Tree by allocating memmory and calling segmentTreeUtil( int *segmentTree(int arr[], int n){ int x = (int)(ceil(log2(n))); int max_size = 2 * (int)pow(2, x) - 1; int *tree = new int[max_size]; segmentTreeUtil(arr, 0, n - 1, tree, 0); return tree; } int main(){ int arr[] = {1, 7, 8, 9, 5, 2, 3, 4}; int n = 8; int *tree = segmentTree(arr, n); int start = 2; int end = 6; cout << "Sum = " << RSQ(tree, n, start, end) << endl; return 0; }
Output
Sum = 27
Time Complexity The time complexity for building the tree is O(N) and the time complexity for each RSQ is O(logn). Thus, for Q queries, the time complexity is O(Q*logN).
Space Complexity O(N)
Conclusion
In conclusion, the Range Sum Query (RSQ) using the Segment Tree is an efficient data structure and algorithm for finding the minimum element in a given range of an array. The time complexity of each query is O(logN) which is better than the naive approach to iterate over the array having a complexity of O(N).