Open In App

Range sum query using Sparse Table

Last Updated : 21 Aug, 2022
Suggest changes
Share
Like Article
Like
Report

We have an array arr[]. We need to find the sum of all the elements in the range L and R where 0 <= L <= R <= n-1. Consider a situation when there are many range queries.

Examples: 

Input : 3 7 2 5 8 9 query(0, 5) query(3, 5) query(2, 4) Output : 34 22 15
Note : array is 0 based indexed and queries too.

Since there are no updates/modifications, we use the Sparse table to answer queries efficiently. In a sparse table, we break queries in powers of 2.  

Suppose we are asked to compute sum of elements from arr[i] to arr[i+12]. We do the following: // Use sum of 8 (or 23) elements table[i][3] = sum(arr[i], arr[i + 1], ... arr[i + 7]). // Use sum of 4 elements table[i+8][2] = sum(arr[i+8], arr[i+9], .. arr[i+11]). // Use sum of single element table[i + 12][0] = sum(arr[i + 12]). Our result is sum of above values.

Notice that it took only 4 actions to compute the result over a subarray of size 13. 

Flowchart:

Flowchart
C++
// CPP program to find the sum in a given // range in an array using sparse table. #include <bits/stdc++.h> using namespace std; // Because 2^17 is larger than 10^5 const int k = 16; // Maximum value of array const int N = 1e5; // k + 1 because we need to access // table[r][k] long long table[N][k + 1]; // it builds sparse table. void buildSparseTable(int arr[], int n) {  for (int i = 0; i < n; i++)  table[i][0] = arr[i];  for (int j = 1; j <= k; j++)  for (int i = 0; i <= n - (1 << j); i++)  table[i][j] = table[i][j - 1] +  table[i + (1 << (j - 1))][j - 1]; } // Returns the sum of the elements in the range // L and R. long long query(int L, int R) {  // boundaries of next query, 0-indexed  long long answer = 0;  for (int j = k; j >= 0; j--) {  if (L + (1 << j) - 1 <= R) {  answer = answer + table[L][j];  // instead of having L', we  // increment L directly  L += 1 << j;  }  }  return answer; } // Driver program. int main() {  int arr[] = { 3, 7, 2, 5, 8, 9 };  int n = sizeof(arr) / sizeof(arr[0]);  buildSparseTable(arr, n);  cout << query(0, 5) << endl;  cout << query(3, 5) << endl;  cout << query(2, 4) << endl;  return 0; } 
Java
// Java program to find the sum  // in a given range in an array  // using sparse table. class GFG {   // Because 2^17 is larger than 10^5 static int k = 16; // Maximum value of array static int N = 100000; // k + 1 because we need // to access table[r][k] static long table[][] = new long[N][k + 1]; // it builds sparse table. static void buildSparseTable(int arr[],  int n) {  for (int i = 0; i < n; i++)  table[i][0] = arr[i];  for (int j = 1; j <= k; j++)  for (int i = 0; i <= n - (1 << j); i++)  table[i][j] = table[i][j - 1] +  table[i + (1 << (j - 1))][j - 1]; } // Returns the sum of the  // elements in the range L and R. static long query(int L, int R) {  // boundaries of next query,  // 0-indexed  long answer = 0;  for (int j = k; j >= 0; j--)   {  if (L + (1 << j) - 1 <= R)   {  answer = answer + table[L][j];  // instead of having L', we  // increment L directly  L += 1 << j;  }  }  return answer; } // Driver Code public static void main(String args[]) {  int arr[] = { 3, 7, 2, 5, 8, 9 };  int n = arr.length;  buildSparseTable(arr, n);  System.out.println(query(0, 5));  System.out.println(query(3, 5));  System.out.println(query(2, 4)); } } // This code is contributed  // by Kirti_Mangal 
C#
// C# program to find the  // sum in a given range // in an array using // sparse table. using System; class GFG {  // Because 2^17 is  // larger than 10^5  static int k = 16;    // Maximum value   // of array  static int N = 100000;    // k + 1 because we   // need to access table[r,k]  static long [,]table =   new long[N, k + 1];    // it builds sparse table.  static void buildSparseTable(int []arr,   int n)  {  for (int i = 0; i < n; i++)  table[i, 0] = arr[i];    for (int j = 1; j <= k; j++)  for (int i = 0;   i <= n - (1 << j); i++)  table[i, j] = table[i, j - 1] +  table[i + (1 << (j - 1)), j - 1];  }     // Returns the sum of the  // elements in the range  // L and R.  static long query(int L, int R)  {  // boundaries of next   // query, 0-indexed  long answer = 0;  for (int j = k; j >= 0; j--)   {  if (L + (1 << j) - 1 <= R)   {  answer = answer +   table[L, j];    // instead of having   // L', we increment   // L directly  L += 1 << j;  }  }  return answer;  }    // Driver Code  static void Main()  {  int []arr = new int[]{3, 7, 2,   5, 8, 9};  int n = arr.Length;    buildSparseTable(arr, n);    Console.WriteLine(query(0, 5));  Console.WriteLine(query(3, 5));  Console.WriteLine(query(2, 4));  } } // This code is contributed by  // Manish Shaw(manishshaw1) 
Python3
# Python3 program to find the sum in a given # range in an array using sparse table. # Because 2^17 is larger than 10^5 k = 16 # Maximum value of array n = 100000 # k + 1 because we need to access # table[r][k] table = [[0 for j in range(k+1)] for i in range(n)] # it builds sparse table def buildSparseTable(arr, n): global table, k for i in range(n): table[i][0] = arr[i] for j in range(1,k+1): for i in range(0,n-(1<<j)+1): table[i][j] = table[i][j-1] + \ table[i + (1 << (j - 1))][j - 1] # Returns the sum of the elements in the range # L and R. def query(L, R): global table, k # boundaries of next query, 0 - indexed answer = 0 for j in range(k,-1,-1): if (L + (1 << j) - 1 <= R): answer = answer + table[L][j] # instead of having L ', we # increment L directly L+=1<<j return answer # Driver program if __name__ == '__main__': arr = [3, 7, 2, 5, 8, 9] n = len(arr) buildSparseTable(arr, n) print(query(0,5)) print(query(3,5)) print(query(2,4)) # This code is contributed by  # chaudhary_19 (Mayank Chaudhary) 
JavaScript
<script> // JavaScript program to find the sum in a given // range in an array using sparse table. // Because 2^17 is larger than 10^5 const k = 16; // Maximum value of array const N = 1e5; // k + 1 because we need to access // table[r][k] const table = new Array(N).fill(0).map(() => new Array(k + 1).fill(0)); // it builds sparse table. function buildSparseTable(arr, n) {  for (let i = 0; i < n; i++)  table[i][0] = arr[i];  for (let j = 1; j <= k; j++)  for (let i = 0; i <= n - (1 << j); i++)  table[i][j] = table[i][j - 1] +  table[i + (1 << (j - 1))][j - 1]; } // Returns the sum of the elements in the range // L and R. function query(L, R) {  // boundaries of next query, 0-indexed  let answer = 0;  for (let j = k; j >= 0; j--)  {  if (L + (1 << j) - 1 <= R)  {  answer = answer + table[L][j];  // instead of having L', we  // increment L directly  L += 1 << j;  }  }  return answer; } // Driver program.  let arr = [ 3, 7, 2, 5, 8, 9 ];  let n = arr.length;  buildSparseTable(arr, n);  document.write(query(0, 5) + "<br>");  document.write(query(3, 5) + "<br>");  document.write(query(2, 4) + "<br>"); // This code is contributed by Manoj. </script> 

Output:  

34 22 15

This algorithm for answering queries with Sparse Table works in O(k), which is O(log(n)) because we choose minimal k such that 2^k+1 > n.
Time complexity of sparse table construction : Outer loop runs in O(k), inner loop runs in O(n). Thus, in total we get O(n * k) = O(n * log(n)) 

Auxiliary Space: O(n*k), since n*k extra space has been taken.


Similar Reads