Range sum queries for anticlockwise rotations of Array by K indices

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]

    otherwise.

Below code is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to calculate range sum
// queries for anticlockwise
// rotations of array by K
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to execute the queries
void rotatedSumQuery(
    int arr[], int n,
    vector<vector<int> >& query,
    int Q)
{
    // Construct a new array
    // of size 2*N to store
    // prefix sum of every index
    int prefix[2 * n];
  
    // Copy elements to the new array
    for (int i = 0; i < n; i++) {
        prefix[i] = arr[i];
        prefix[i + n] = arr[i];
    }
  
    // Calculate the prefix sum
    // for every index
    for (int i = 1; i < 2 * n; i++)
        prefix[i] += prefix[i - 1];
  
    // Set start pointer as 0
    int start = 0;
  
    for (int q = 0; q < Q; q++) {
  
        // Query to perform
        // anticlockwise rotation
        if (query[q][0] == 1) {
            int k = query[q][1];
            start = (start + k) % n;
        }
  
        // Query to answer range sum
        else if (query[q][0] == 2) {
  
            int L, R;
            L = query[q][1];
            R = query[q][2];
  
            // If pointing to 1st index
            if (start + L == 0)
  
                // Display the sum upto start + R
                cout << prefix[start + R] << endl;
  
            else
  
                // Subtract sum upto start + L - 1
                // from sum upto start + R
                cout << prefix[start + R]
                            - prefix[start + L - 1]
                     << endl;
        }
    }
}
  
// Driver code
int main()
{
  
    int arr[] = { 1, 2, 3, 4, 5, 6 };
  
    // Number of query
    int Q = 5;
  
    // Store all the queries
    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;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to calculate range sum
// queries for anticlockwise
// rotations of array by K
class GFG{
  
// Function to execute the queries
static void rotatedSumQuery(int arr[], int n,
                            int [][]query, int Q)
{
      
    // Construct a new array
    // of size 2*N to store
    // prefix sum of every index
    int []prefix = new int[2 * n];
  
    // Copy elements to the new array
    for(int i = 0; i < n; i++)
    {
        prefix[i] = arr[i];
        prefix[i + n] = arr[i];
    }
  
    // Calculate the prefix sum
    // for every index
    for(int i = 1; i < 2 * n; i++)
        prefix[i] += prefix[i - 1];
  
    // Set start pointer as 0
    int start = 0;
  
    for(int q = 0; q < Q; q++)
    {
  
        // Query to perform
        // anticlockwise rotation
        if (query[q][0] == 1)
        {
            int k = query[q][1];
            start = (start + k) % n;
        }
  
        // Query to answer range sum
        else if (query[q][0] == 2
        {
            int L, R;
            L = query[q][1];
            R = query[q][2];
  
            // If pointing to 1st index
            if (start + L == 0)
  
                // Display the sum upto start + R
                System.out.print(prefix[start + R] + "\n");
  
            else
  
                // Subtract sum upto start + L - 1
                // from sum upto start + R
                System.out.print(prefix[start + R] -
                                 prefix[start + L - 1] + 
                                 "\n");
        }
    }
}
  
// Driver code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 4, 5, 6 };
  
    // Number of query
    int Q = 5;
  
    // Store all the queries
    int [][]query = { { 2, 1, 3 },
                      { 1, 3 },
                      { 2, 0, 3 },
                      { 1, 4 },
                      { 2, 3, 5 } };
  
    int n = arr.length;
    rotatedSumQuery(arr, n, query, Q);
}
}
  
// This code is contributed by Rohit_ranjan

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to calculate range sum
# queries for anticlockwise
# rotations of the array by K
  
# Function to execute the queries
def rotatedSumQuery(arr, n, query, Q):
  
    # Construct a new array
    # of size 2*N to store
    # prefix sum of every index
    prefix = [0] * (2 * n)
  
    # Copy elements to the new array
    for i in range(n):
        prefix[i] = arr[i]
        prefix[i + n] = arr[i]
  
    # Calculate the prefix sum
    # for every index
    for i in range(1, 2 * n):
        prefix[i] += prefix[i - 1];
  
    # Set start pointer as 0
    start = 0;
  
    for q in range(Q):
  
        # Query to perform
        # anticlockwise rotation
        if (query[q][0] == 1):
            k = query[q][1]
            start = (start + k) % n;
  
        # Query to answer range sum
        elif (query[q][0] == 2):
            L = query[q][1]
            R = query[q][2]
  
            # If pointing to 1st index
            if (start + L == 0):
  
                # Display the sum upto start + R
                print(prefix[start + R])
  
            else:
  
                # Subtract sum upto start + L - 1
                # from sum upto start + R
                print(prefix[start + R]- 
                      prefix[start + L - 1])
          
# Driver code
arr = [ 1, 2, 3, 4, 5, 6 ];
  
# Number of query
Q = 5
  
# Store all the queries
query= [ [ 2, 1, 3 ],
         [ 1, 3 ],
         [ 2, 0, 3 ],
         [ 1, 4 ],
         [ 2, 3, 5 ] ]
  
n = len(arr);
rotatedSumQuery(arr, n, query, Q);
  
# This code is contributed by ankitkumar34

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to calculate range sum
// queries for anticlockwise
// rotations of array by K
using System;
  
class GFG{
  
// Function to execute the queries
static void rotatedSumQuery(int[] arr, int n,
                            int[,] query, int Q)
{
      
    // Construct a new array
    // of size 2*N to store
    // prefix sum of every index
    int[] prefix = new int[2 * n];
  
    // Copy elements to the new array
    for(int i = 0; i < n; i++)
    {
        prefix[i] = arr[i];
        prefix[i + n] = arr[i];
    }
  
    // Calculate the prefix sum
    // for every index
    for(int i = 1; i < 2 * n; i++)
        prefix[i] += prefix[i - 1];
  
    // Set start pointer as 0
    int start = 0;
  
    for(int q = 0; q < Q; q++)
    {
  
        // Query to perform
        // anticlockwise rotation
        if (query[q, 0] == 1)
        {
            int k = query[q, 1];
            start = (start + k) % n;
        }
  
        // Query to answer range sum
        else if (query[q, 0] == 2) 
        {
            int L, R;
            L = query[q, 1];
            R = query[q, 2];
  
            // If pointing to 1st index
            if (start + L == 0)
  
                // Display the sum upto start + R
                Console.Write(prefix[start + R] + "\n");
  
            else
  
                // Subtract sum upto start + L - 1
                // from sum upto start + R
                Console.Write(prefix[start + R] -
                              prefix[start + L - 1] + 
                              "\n");
        }
    }
}
  
// Driver code
public static void Main()
{
    int[] arr = new int[] { 1, 2, 3, 4, 5, 6 };
  
    // Number of query
    int Q = 5;
  
    // Store all the queries
    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);
}
}
  
// This code is contributed by sanjoy_62

chevron_right


Output:

9
16
12

Time Complexity: O(1) for every query.
Auxiliary Space Complexity: O(N)

competitive-programming-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.