Range sum queries for anticlockwise rotations of Array by K indices
Last Updated :
25 Apr, 2023
Given an array arr consisting of N elements and Q queries of the following two types:
- 1 K: For this type of query, the array needs to be rotated by K indices anticlockwise from its current state.
- 2 L R: For this query, the sum of the array elements present in the indices [L, R] needs to be calculated.
Example:
Input: arr = { 1, 2, 3, 4, 5, 6 }, query = { {2, 1, 3}, {1, 3}, {2, 0, 3}, {1, 4}, {2, 3, 5} }
Output:
9
16
12
Explanation:
For the 1st query {2, 1, 3} -> Sum of the elements in the indices [1, 3] = 2 + 3 + 4 = 9.
For the 2nd query {1, 3} -> Modified array after anti-clockwise rotation by 3 places is { 4, 5, 6, 1, 2, 3 }
For the 3rd query {2, 0, 3} -> Sum of the elements in the indices [0, 3] = 4 + 5 + 6 + 1 = 16.
For the 4th query {1, 4} -> Modified array after anti-clockwise rotation by 4 places is { 2, 3, 4, 5, 6, 1 }
For the 5th query {2, 3, 5} -> Sum of the elements in the indices [3, 5] = 5 + 6 + 1 = 12.
Approach:
- Create a prefix array which is double the size of the arr and copy the element at the ith index of arr to ith and N + ith index of prefix for all i in [0, N).
- Precompute the prefix sum for every index of that array and store in prefix.
- Set the pointer start at 0 to denote the starting index of the initial array.
- For query of type 1, shift start to
((start + K) % N)th position
- For query of type 2, calculate
prefix[start + R]
- prefix[start + L- 1 ]
- if start + L >= 1 or print the value of
prefix[start + R]
Below code is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void rotatedSumQuery(
int arr[], int n,
vector<vector< int > >& query,
int Q)
{
int prefix[2 * n];
for ( int i = 0; i < n; i++) {
prefix[i] = arr[i];
prefix[i + n] = arr[i];
}
for ( int i = 1; i < 2 * n; i++)
prefix[i] += prefix[i - 1];
int start = 0;
for ( int q = 0; q < Q; q++) {
if (query[q][0] == 1) {
int k = query[q][1];
start = (start + k) % n;
}
else if (query[q][0] == 2) {
int L, R;
L = query[q][1];
R = query[q][2];
if (start + L == 0)
cout << prefix[start + R] << endl;
else
cout << prefix[start + R]
- prefix[start + L - 1]
<< endl;
}
}
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6 };
int Q = 5;
vector<vector< int > > query
= { { 2, 1, 3 },
{ 1, 3 },
{ 2, 0, 3 },
{ 1, 4 },
{ 2, 3, 5 } };
int n = sizeof (arr) / sizeof (arr[0]);
rotatedSumQuery(arr, n, query, Q);
return 0;
}
|
Java
class GFG{
static void rotatedSumQuery( int arr[], int n,
int [][]query, int Q)
{
int []prefix = new int [ 2 * n];
for ( int i = 0 ; i < n; i++)
{
prefix[i] = arr[i];
prefix[i + n] = arr[i];
}
for ( int i = 1 ; i < 2 * n; i++)
prefix[i] += prefix[i - 1 ];
int start = 0 ;
for ( int q = 0 ; q < Q; q++)
{
if (query[q][ 0 ] == 1 )
{
int k = query[q][ 1 ];
start = (start + k) % n;
}
else if (query[q][ 0 ] == 2 )
{
int L, R;
L = query[q][ 1 ];
R = query[q][ 2 ];
if (start + L == 0 )
System.out.print(prefix[start + R] + "\n" );
else
System.out.print(prefix[start + R] -
prefix[start + L - 1 ] +
"\n" );
}
}
}
public static void main(String[] args)
{
int arr[] = { 1 , 2 , 3 , 4 , 5 , 6 };
int Q = 5 ;
int [][]query = { { 2 , 1 , 3 },
{ 1 , 3 },
{ 2 , 0 , 3 },
{ 1 , 4 },
{ 2 , 3 , 5 } };
int n = arr.length;
rotatedSumQuery(arr, n, query, Q);
}
}
|
Python3
def rotatedSumQuery(arr, n, query, Q):
prefix = [ 0 ] * ( 2 * n)
for i in range (n):
prefix[i] = arr[i]
prefix[i + n] = arr[i]
for i in range ( 1 , 2 * n):
prefix[i] + = prefix[i - 1 ];
start = 0 ;
for q in range (Q):
if (query[q][ 0 ] = = 1 ):
k = query[q][ 1 ]
start = (start + k) % n;
elif (query[q][ 0 ] = = 2 ):
L = query[q][ 1 ]
R = query[q][ 2 ]
if (start + L = = 0 ):
print (prefix[start + R])
else :
print (prefix[start + R] -
prefix[start + L - 1 ])
arr = [ 1 , 2 , 3 , 4 , 5 , 6 ];
Q = 5
query = [ [ 2 , 1 , 3 ],
[ 1 , 3 ],
[ 2 , 0 , 3 ],
[ 1 , 4 ],
[ 2 , 3 , 5 ] ]
n = len (arr);
rotatedSumQuery(arr, n, query, Q);
|
C#
using System;
class GFG{
static void rotatedSumQuery( int [] arr, int n,
int [,] query, int Q)
{
int [] prefix = new int [2 * n];
for ( int i = 0; i < n; i++)
{
prefix[i] = arr[i];
prefix[i + n] = arr[i];
}
for ( int i = 1; i < 2 * n; i++)
prefix[i] += prefix[i - 1];
int start = 0;
for ( int q = 0; q < Q; q++)
{
if (query[q, 0] == 1)
{
int k = query[q, 1];
start = (start + k) % n;
}
else if (query[q, 0] == 2)
{
int L, R;
L = query[q, 1];
R = query[q, 2];
if (start + L == 0)
Console.Write(prefix[start + R] + "\n" );
else
Console.Write(prefix[start + R] -
prefix[start + L - 1] +
"\n" );
}
}
}
public static void Main()
{
int [] arr = new int [] { 1, 2, 3, 4, 5, 6 };
int Q = 5;
int [,] query = new int [,] { { 2, 1, 3 },
{ 1, 3, 0 },
{ 2, 0, 3 },
{ 1, 4, 0 },
{ 2, 3, 5 } };
int n = arr.Length;
rotatedSumQuery(arr, n, query, Q);
}
}
|
Javascript
<script>
function rotatedSumQuery(arr, n,
query, Q)
{
let prefix = [];
for (let i = 0; i < n; i++)
{
prefix[i] = arr[i];
prefix[i + n] = arr[i];
}
for (let i = 1; i < 2 * n; i++)
prefix[i] += prefix[i - 1];
let start = 0;
for (let q = 0; q < Q; q++)
{
if (query[q][0] == 1)
{
let k = query[q][1];
start = (start + k) % n;
}
else if (query[q][0] == 2)
{
let L, R;
L = query[q][1];
R = query[q][2];
if (start + L == 0)
document.write(prefix[start + R] + "<br/>" );
else
document.write(prefix[start + R] -
prefix[start + L - 1] +
"<br/>" );
}
}
}
let arr = [ 1, 2, 3, 4, 5, 6 ];
let Q = 5;
let query = [[ 2, 1, 3 ],
[ 1, 3 ],
[ 2, 0, 3 ],
[ 1, 4 ],
[ 2, 3, 5 ]];
let n = arr.length;
rotatedSumQuery(arr, n, query, Q);
</script>
|
Time Complexity: O(N+Q), where Q is the number of queries, and as each query will cost O (1) time for Q queries time complexity would be O(N+Q).
Auxiliary Space: O(N), as we are using extra space for prefix.
Share your thoughts in the comments
Please Login to comment...