Queries to calculate sum of array elements present at every Yth index starting from the index X
Last Updated :
02 May, 2023
Given an array arr[] of size N, and an array Q[][] with each row representing a query of the form { X, Y }, the task for each query is to find the sum of array elements present at indices X, X + Y, X + 2 * Y + …
Examples:
Input: arr[] = { 1, 2, 7, 5, 4 }, Q[][] = { { 2, 1 }, { 3, 2 } }
Output: 16 5
Explanation:
Query1: arr[2] + arr[2 + 1] + arr[2 + 2] = 7 + 5 + 4 = 16.
Query2: arr[3] = 5.
Input: arr[] = { 3, 6, 1, 8, 0 } Q[][] = { { 0, 2 } }
Output: 4
Naive Approach: The simplest approach to solve this problem is to traverse the array for each query and print the sum of arr[x] + arr[x + y] + arr[x + 2 * y] + …
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void querySum( int arr[], int N,
int Q[][2], int M)
{
for ( int i = 0; i < M; i++) {
int x = Q[i][0];
int y = Q[i][1];
int sum = 0;
while (x < N) {
sum += arr[x];
x += y;
}
cout << sum << " " ;
}
}
int main()
{
int arr[] = { 1, 2, 7, 5, 4 };
int Q[][2] = { { 2, 1 }, { 3, 2 } };
int N = sizeof (arr) / sizeof (arr[0]);
int M = sizeof (Q) / sizeof (Q[0]);
querySum(arr, N, Q, M);
return 0;
}
|
Java
import java.util.*;
class GFG{
static void querySum( int arr[], int N,
int Q[][], int M)
{
for ( int i = 0 ; i < M; i++)
{
int x = Q[i][ 0 ];
int y = Q[i][ 1 ];
int sum = 0 ;
while (x < N)
{
sum += arr[x];
x += y;
}
System.out.print(sum + " " );
}
}
public static void main(String[] args)
{
int arr[] = { 1 , 2 , 7 , 5 , 4 };
int Q[][] = { { 2 , 1 }, { 3 , 2 } };
int N = arr.length;
int M = Q.length;
querySum(arr, N, Q, M);
}
}
|
Python3
def querySum(arr, N, Q, M):
for i in range (M):
x = Q[i][ 0 ]
y = Q[i][ 1 ]
sum = 0
while (x < N):
sum + = arr[x]
x + = y
print ( sum , end = " " )
if __name__ = = '__main__' :
arr = [ 1 , 2 , 7 , 5 , 4 ];
Q = [ [ 2 , 1 ], [ 3 , 2 ] ]
N = len (arr)
M = len (Q)
querySum(arr, N, Q, M)
|
C#
using System;
class GFG
{
static void querySum( int []arr, int N,
int [,]Q, int M)
{
for ( int i = 0; i < M; i++)
{
int x = Q[i, 0];
int y = Q[i, 1];
int sum = 0;
while (x < N)
{
sum += arr[x];
x += y;
}
Console.Write(sum + " " );
}
}
public static void Main(String[] args)
{
int []arr = { 1, 2, 7, 5, 4 };
int [,]Q = { { 2, 1 }, { 3, 2 } };
int N = arr.Length;
int M = Q.GetLength(0);
querySum(arr, N, Q, M);
}
}
|
Javascript
<script>
function querySum(arr, N, Q, M)
{
for (let i = 0; i < M; i++) {
let x = Q[i][0];
let y = Q[i][1];
let sum = 0;
while (x < N) {
sum += arr[x];
x += y;
}
document.write(sum + " " );
}
}
let arr = [ 1, 2, 7, 5, 4 ];
let Q = [ [ 2, 1 ], [ 3, 2 ] ];
let N = arr.length;
let M = Q.length;
querySum(arr, N, Q, M);
</script>
|
Time Complexity: O(|Q| * O(N))
Auxiliary Space: O(1)
The problem can be solved by precomputing the value of the given expression for all possible values of { X, Y } using Dynamic programming technique and the Square Root Decomposition technique. The following are the recurrence relation:
if i + j < N
dp[i][j] = dp[i + j][j] + arr[i]
Otherwise,
dp[i][j] = arr[i]
dp[i][j]: Stores the sum of the given expression where X = i, Y = j
Follow the steps below to solve the problem:
- Initialize a 2D array, say dp[][], to store the sum of expression for all possible values of X and Y, where Y is less than or equal to sqrt(N).
- Fill the dp[][] array using tabulation method.
- Traverse the array Q[][]. For each query, check if the value of Q[i][1] is less than or equal to sqrt(N) or not. If found to be true, then print the value of dp[Q[i][0]][Q[i][1]].
- Otherwise, calculate the value of the expression using the above naive approach and print the calculated value.
Below is the implementation of our approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int sz = 20;
const int sqr = int ( sqrt (sz)) + 1;
void precomputeExpressionForAllVal( int arr[], int N,
int dp[sz][sqr])
{
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 1; j <= sqrt (N); j++) {
if (i + j < N) {
dp[i][j] = arr[i] + dp[i + j][j];
}
else {
dp[i][j] = arr[i];
}
}
}
}
int querySum( int arr[], int N,
int Q[][2], int M)
{
int dp[sz][sqr];
precomputeExpressionForAllVal(arr, N, dp);
for ( int i = 0; i < M; i++) {
int x = Q[i][0];
int y = Q[i][1];
if (y <= sqrt (N)) {
cout << dp[x][y] << " " ;
continue ;
}
int sum = 0;
while (x < N) {
sum += arr[x];
x += y;
}
cout << sum << " " ;
}
}
int main()
{
int arr[] = { 1, 2, 7, 5, 4 };
int Q[][2] = { { 2, 1 }, { 3, 2 } };
int N = sizeof (arr) / sizeof (arr[0]);
int M = sizeof (Q) / sizeof (Q[0]);
querySum(arr, N, Q, M);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int sz = 20 ;
static int sqr = ( int )(Math.sqrt(sz)) + 1 ;
static void precomputeExpressionForAllVal( int arr[],
int N,
int dp[][])
{
for ( int i = N - 1 ; i >= 0 ; i--)
{
for ( int j = 1 ; j <= Math.sqrt(N); j++)
{
if (i + j < N)
{
dp[i][j] = arr[i] + dp[i + j][j];
}
else
{
dp[i][j] = arr[i];
}
}
}
}
static void querySum( int arr[], int N,
int Q[][], int M)
{
int [][]dp = new int [sz][sqr];
precomputeExpressionForAllVal(arr, N, dp);
for ( int i = 0 ; i < M; i++)
{
int x = Q[i][ 0 ];
int y = Q[i][ 1 ];
if (y <= Math.sqrt(N))
{
System.out.print(dp[x][y] + " " );
continue ;
}
int sum = 0 ;
while (x < N)
{
sum += arr[x];
x += y;
}
System.out.print(sum + " " );
}
}
public static void main(String[] args)
{
int arr[] = { 1 , 2 , 7 , 5 , 4 };
int Q[][] = { { 2 , 1 }, { 3 , 2 } };
int N = arr.length;
int M = Q.length;
querySum(arr, N, Q, M);
}
}
|
Python3
import math
sz = 20
sqr = int (math.sqrt(sz)) + 1
def precomputeExpressionForAllVal(arr, N, dp):
for i in range (N - 1 , - 1 , - 1 ) :
for j in range ( 1 , int (math.sqrt(N)) + 1 ):
if (i + j < N):
dp[i][j] = arr[i] + dp[i + j][j]
else :
dp[i][j] = arr[i]
def querySum(arr, N, Q, M):
dp = [ [ 0 for x in range (sz)] for x in range (sqr)]
precomputeExpressionForAllVal(arr, N, dp)
for i in range ( 0 ,M):
x = Q[i][ 0 ]
y = Q[i][ 1 ]
if (y < = math.sqrt(N)):
print (dp[x][y])
continue
sum = 0
while (x < N):
sum + = arr[x]
x + = y
print ( sum )
arr = [ 1 , 2 , 7 , 5 , 4 ]
Q = [ [ 2 , 1 ], [ 3 , 2 ]]
N = len (arr)
M = len (Q[ 0 ])
querySum(arr, N, Q, M)
|
C#
using System;
class GFG{
static int sz = 20;
static int sqr = ( int )(Math.Sqrt(sz)) + 1;
static void precomputeExpressionForAllVal( int []arr,
int N,
int [,]dp)
{
for ( int i = N - 1; i >= 0; i--)
{
for ( int j = 1; j <= Math.Sqrt(N); j++)
{
if (i + j < N)
{
dp[i, j] = arr[i] + dp[i + j, j];
}
else
{
dp[i, j] = arr[i];
}
}
}
}
static void querySum( int []arr, int N,
int [,]Q, int M)
{
int [,]dp = new int [sz, sqr];
precomputeExpressionForAllVal(arr, N, dp);
for ( int i = 0; i < M; i++)
{
int x = Q[i, 0];
int y = Q[i, 1];
if (y <= Math.Sqrt(N))
{
Console.Write(dp[x, y] + " " );
continue ;
}
int sum = 0;
while (x < N)
{
sum += arr[x];
x += y;
}
Console.Write(sum + " " );
}
}
public static void Main(String[] args)
{
int []arr = { 1, 2, 7, 5, 4 };
int [,]Q = { { 2, 1 }, { 3, 2 } };
int N = arr.Length;
int M = Q.GetLength(0);
querySum(arr, N, Q, M);
}
}
|
Javascript
<script>
let sz = 20;
let sqr = (Math.sqrt(sz)) + 1;
function precomputeExpressionForAllVal(arr, N, dp)
{
for (let i = N - 1; i >= 0; i--)
{
for (let j = 1; j <= Math.sqrt(N); j++)
{
if (i + j < N)
{
dp[i][j] = arr[i] + dp[i + j][j];
}
else
{
dp[i][j] = arr[i];
}
}
}
}
function querySum(arr, N, Q, M)
{
let dp = new Array(sz);
for ( var i = 0; i < dp.length; i++) {
dp[i] = new Array(2);
}
for ( var i = 0; i < dp.length; i++) {
dp[i] = new Array(2);
}
precomputeExpressionForAllVal(arr, N, dp);
for (let i = 0; i < M; i++)
{
let x = Q[i][0];
let y = Q[i][1];
if (y <= Math.sqrt(N))
{
document.write(dp[x][y] + " " );
continue ;
}
let sum = 0;
while (x < N)
{
sum += arr[x];
x += y;
}
Sdocument.write(sum + " " );
}
}
let arr = [ 1, 2, 7, 5, 4 ];
let Q= [[ 2, 1 ], [ 3, 2 ]]
let N = arr.length;
let M = Q.length;
querySum(arr, N, Q, M);
</script>
|
Time complexity: O(N * sqrt(N) + |Q| * sqrt(N))
Auxiliary Space:O(N * sqrt(N))
Approach 2B: Space optimization
In the previous approach, we can see that in the function precomputeExpressionForAllVal we use 2d dp which is not required because dp[i][j] is dependent upon arr[i] and dp[i + j][j] so we can optimize its space complexity by using 1d DP.
Implementation:
- Initialize dp to all zeros and Iterate over all possible values of X from N-1 down to 0.
- Precompute for all possible values of an expression such that y <= sqrt(N).
- If i + j is less than N, update dp[i] to add arr[i+j].
- Define the function querySum to take in the input parameters arr, N, Q, and M.
- Traverse the query array Q[][], where each query is represented by a pair of integers {x, y}.
- If y is less than or equal to sqrt(N), iterate over arr[x], arr[x+y], arr[x+2y],…, until the end of the array and print their sum.
- Otherwise, for each query, initialize sum to zero and traverse the array arr[] starting from index x and incrementing by y.
- Add each element arr[i] to sum until x is less than N.
- Print the final sum for each query.
Example:
C++
#include <bits/stdc++.h>
using namespace std;
void precomputeExpressionForAllVal( int arr[], int N,
int dp[])
{
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 1; j <= sqrt (N); j++) {
if (i + j < N) {
dp[i] += arr[i + j];
}
}
}
}
void querySum( int arr[], int N, int Q[][2], int M)
{
for ( int i = 0; i < M; i++) {
int x = Q[i][0];
int y = Q[i][1];
if (y <= sqrt (N)) {
int ans = 0;
for ( int j = x; j < N; j += y)
ans += arr[j];
cout << ans << " " ;
continue ;
}
int sum = 0;
while (x < N) {
sum += arr[x];
x += y;
}
cout << sum << " " ;
}
}
int main()
{
int arr[] = { 1, 2, 7, 5, 4 };
int Q[][2] = { { 2, 1 }, { 3, 2 } };
int N = sizeof (arr) / sizeof (arr[0]);
int M = sizeof (Q) / sizeof (Q[0]);
int dp[N] = { 0 };
precomputeExpressionForAllVal(arr, N, dp);
querySum(arr, N, Q, M);
return 0;
}
|
Java
import java.util.*;
public class Main {
static void precomputeExpressionForAllVal( int [] arr,
int N,
int [] dp)
{
for ( int i = N - 1 ; i >= 0 ; i--) {
for ( int j = 1 ; j <= Math.sqrt(N); j++) {
if (i + j < N) {
dp[i] += arr[i + j];
}
}
}
}
static void querySum( int [] arr, int N, int [][] Q, int M)
{
for ( int i = 0 ; i < M; i++) {
int x = Q[i][ 0 ];
int y = Q[i][ 1 ];
if (y <= Math.sqrt(N)) {
int ans = 0 ;
for ( int j = x; j < N; j += y)
ans += arr[j];
System.out.print(ans + " " );
continue ;
}
int sum = 0 ;
while (x < N) {
sum += arr[x];
x += y;
}
System.out.print(sum + " " );
}
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 7 , 5 , 4 };
int [][] Q = { { 2 , 1 }, { 3 , 2 } };
int N = arr.length;
int M = Q.length;
int [] dp = new int [N];
precomputeExpressionForAllVal(arr, N, dp);
querySum(arr, N, Q, M);
}
}
|
Python3
import math
def precompute_expression_for_all_val(arr, N, dp):
for i in range (N - 1 , - 1 , - 1 ):
for j in range ( 1 , int (math.sqrt(N)) + 1 ):
if i + j < N:
dp[i] + = arr[i + j]
def query_sum(arr, N, Q, M):
for i in range (M):
x = Q[i][ 0 ]
y = Q[i][ 1 ]
if y < = int (math.sqrt(N)):
ans = 0
for j in range (x, N, y):
ans + = arr[j]
print (ans, end = " " )
continue
sum = 0
while x < N:
sum + = arr[x]
x + = y
print ( sum , end = " " )
arr = [ 1 , 2 , 7 , 5 , 4 ]
Q = [[ 2 , 1 ], [ 3 , 2 ]]
N = len (arr)
M = len (Q)
dp = [ 0 ] * N
precompute_expression_for_all_val(arr, N, dp)
query_sum(arr, N, Q, M)
|
C#
using System;
class Program {
static void PrecomputeExpressionForAllVal( int [] arr,
int N,
int [] dp)
{
for ( int i = N - 1; i >= 0; i--) {
for ( int j = 1; j <= Math.Sqrt(N); j++) {
if (i + j < N) {
dp[i] += arr[i + j];
}
}
}
}
static void QuerySum( int [] arr, int N, int [][] Q, int M)
{
for ( int i = 0; i < M; i++) {
int x = Q[i][0];
int y = Q[i][1];
if (y <= Math.Sqrt(N)) {
int ans = 0;
for ( int j = x; j < N; j += y) {
ans += arr[j];
}
Console.Write(ans + " " );
continue ;
}
int sum = 0;
while (x < N) {
sum += arr[x];
x += y;
}
Console.Write(sum + " " );
}
}
static void Main( string [] args)
{
int [] arr = { 1, 2, 7, 5, 4 };
int [][] Q
= { new int [] { 2, 1 }, new int [] { 3, 2 } };
int N = arr.Length;
int M = Q.Length;
int [] dp = new int [N];
PrecomputeExpressionForAllVal(arr, N, dp);
QuerySum(arr, N, Q, M);
}
}
|
Javascript
function precomputeExpressionForAllVal(arr, N) {
const dp = new Array(N).fill(0);
for (let i = N - 1; i >= 0; i--) {
for (let j = 1; j <= Math.sqrt(N); j++) {
if (i + j < N) {
dp[i] += arr[i + j];
}
}
}
return dp;
}
function querySum(arr, N, Q, M) {
for (let i = 0; i < M; i++) {
const x = Q[i][0];
const y = Q[i][1];
if (y <= Math.sqrt(N)) {
let ans = 0;
for (let j = x; j < N; j += y) {
ans += arr[j];
}
console.log(ans + " " );
continue ;
}
let sum = 0;
while (x < N) {
sum += arr[x];
x += y;
}
console.log(sum + " " );
}
}
const arr = [1, 2, 7, 5, 4];
const Q = [
[2, 1],
[3, 2]
];
const N = arr.length;
const M = Q.length;
const dp = precomputeExpressionForAllVal(arr, N);
querySum(arr, N, Q, M);
|
Output:
16 5
Time complexity: O(N * sqrt(N) + |Q| * sqrt(N))
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...