Given an array arr[] of N integers. There are three types of commands:
- 1 x: Right Circular Shift the array x times. If an array is a[0], a[1], …., a[n – 1], then after one right circular shift the array will become a[n – 1], a[0], a[1], …., a[n – 2].
- 2 y: Left Circular Shift the array y times. If an array is a[0], a[1], …., a[n – 1], then after one left circular shift the array will become a[1], …., a[n – 2], a[n – 1], a[0].
- 3 l r: Print the sum of all integers in the subarray a[l…r] (l and r inclusive).
Given Q queries, the task is to execute each query.
Examples:
Input: N = 5, arr[] = { 1, 2, 3, 4, 5 },
query 1 = { 1, 3 }
query 2 = { 3, 0, 2 }
query 3 = { 2, 1 }
query 4 = { 3, 1, 4 }
Output: 12,11
Explanation: Initial array arr[] = { 1, 2, 3, 4, 5 }
After query 1, arr[] = { 3, 4, 5, 1, 2 }
After query 2, sum from index 0 to index 2 is 12,
So output 12.
After query 3, arr[] = { 4, 5, 1, 2, 3 }
After query 4, sum from index 1 to index 4 is 11.
So output 11.
Input: N = 5, arr[] = { 1, 2, 3, 4, 5 }
query 1 = { 2, 1 }
query 2 = { 3, 0, 2 }
query 3 = { 1, 3 }
query 4 = { 3, 1, 4 }
Output: 9, 11
Explanation:
Initial array arr[] = { 1, 2, 3, 4, 5 }
After query 1, arr[] = {2, 3, 4, 5, 1 }
After query 2, sum from index 0 to index 2 is 9.
So output 9.
After query 3, arr[] = { 4, 5, 1, 2, 3}
After query 4, sum from index 1 to index 4 is 11.
So output 11.
Approach 1 (Brute Approach): The basic idea is as follows:
For each type of query, perform the mentioned task. In each query either do left rotation, or right rotation or find the sum of the elements in the given range.
Time Complexity: O(N * Q) where Q is the number of queries.
Auxiliary Space: O(1)
Approach 2 (Efficient Approach): The approach is based on the concept of prefix sum and array rotation as follows:
Initially the array is not rotated. So, calculate the net rotation of the array. A negative net rotation means right rotation and positive net rotation means left rotation. Whenever there is a query asking for the sum of a range provide the sum of the elements that will be in that range after the net rotation till that index.
Follow the below steps to implement the idea:
- Calculate the prefix sum of the given array.
- We just need to track the net rotation.
- If the tracked number is negative, It means left rotation has dominated else right rotation has dominated.
- When tracking the net rotations, calculate the net rotation mod N.
- If there is a need to answer any query of a third type and the boundaries are l and r:
- Find what l and r were in the original order.
- We can easily find it out by adding the net rotations to the index and taking mod N.
- Use the prefix sum array to find the sum of the given range in constant time.
Follow the below illustration for a better understanding:
Illustration:
Initial array arr[] = { 1, 2, 3, 4, 5 } and the queries are
query 1 = {2, 1}
query 2 = {3, 0, 2}
query 3 = {1, 3}
query 4 = {3, 1, 4}
The prefixsum[] = { 1, 3, 6, 10, 15 }
query 1 = {2, 1}:
=> Net rotation = 1
query 2 = { 3, 0, 2 }:
=> Net rotation = 1
=> Say l = 0, r = 2.
=> Value of l in original order = 1 and r in original order = 3.
=> Therefore, the sum = 10 – 1 = 9.
query 3 = {1, 3}:
=> Net rotation = 1 – 3 = -2
query 4 = {3, 1, 4}:
=> Net rotation = -2
=> Say l = 1, r = 4.
=> Value of l in original order = (1 – 2 + 5)%5 = 4
=> Value of r in original order = (4 – 2 + 5)%5 = 2
=> The sum = (15 – 10) + 6 = 11
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void querytype1( int * toRotate, int times, int n)
{
(*toRotate) = ((*toRotate) - times) % n;
}
void querytype2( int * toRotate, int times, int n)
{
(*toRotate) = ((*toRotate) + times) % n;
}
void querytype3( int toRotate, int l, int r, int preSum[],
int n)
{
l = (l + toRotate + n) % n;
r = (r + toRotate + n) % n;
if (l <= r)
cout << (preSum[r + 1] - preSum[l]) << endl;
else
cout << (preSum[n] + preSum[r + 1] - preSum[l])
<< endl;
}
void wrapper( int a[], int n)
{
int preSum[n + 1];
preSum[0] = 0;
for ( int i = 1; i <= n; i++)
preSum[i] = preSum[i - 1] + a[i - 1];
int toRotate = 0;
querytype1(&toRotate, 3, n);
querytype3(toRotate, 0, 2, preSum, n);
querytype2(&toRotate, 1, n);
querytype3(toRotate, 1, 4, preSum, n);
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int N = sizeof (arr) / sizeof (arr[0]);
wrapper(arr, N);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int querytype1( int toRotate, int times, int n)
{
toRotate = (toRotate - times) % n;
return toRotate;
}
static int querytype2( int toRotate, int times, int n)
{
toRotate = (toRotate + times) % n;
return toRotate;
}
static void querytype3( int toRotate, int l, int r,
int preSum[], int n)
{
l = (l + toRotate + n) % n;
r = (r + toRotate + n) % n;
if (l <= r)
System.out.println(preSum[r + 1 ] - preSum[l]);
else
System.out.println(preSum[n] + preSum[r + 1 ]
- preSum[l]);
}
static void wrapper( int a[], int n)
{
int preSum[] = new int [n + 1 ];
preSum[ 0 ] = 0 ;
for ( int i = 1 ; i <= n; i++)
preSum[i] = preSum[i - 1 ] + a[i - 1 ];
int toRotate = 0 ;
toRotate = querytype1(toRotate, 3 , n);
querytype3(toRotate, 0 , 2 , preSum, n);
toRotate = querytype2(toRotate, 1 , n);
querytype3(toRotate, 1 , 4 , preSum, n);
}
public static void main(String args[])
{
int arr[] = { 1 , 2 , 3 , 4 , 5 };
int N = arr.length;
wrapper(arr, N);
}
}
|
Python3
def querytype1(toRotate, times, n):
toRotate = (toRotate - times) % n
return toRotate
def querytype2(toRotate, times, n):
toRotate = (toRotate + times) % n
return toRotate
def querytype3( toRotate, l, r, preSum, n):
l = (l + toRotate + n) % n
r = (r + toRotate + n) % n
if (l < = r):
print ((preSum[r + 1 ] - preSum[l]))
else :
print ((preSum[n] + preSum[r + 1 ] - preSum[l]))
def wrapper( a, n):
preSum = [ 0 for i in range (n + 1 )]
for i in range ( 1 ,n + 1 ):
preSum[i] = preSum[i - 1 ] + a[i - 1 ]
toRotate = 0
toRotate = querytype1(toRotate, 3 , n)
querytype3(toRotate, 0 , 2 , preSum, n)
toRotate = querytype2(toRotate, 1 , n)
querytype3(toRotate, 1 , 4 , preSum, n);
if __name__ = = '__main__' :
arr = [ 1 , 2 , 3 , 4 , 5 ]
N = len (arr)
wrapper(arr, N)
|
C#
using System;
class GFG {
static int querytype1( int toRotate, int times, int n)
{
toRotate = (toRotate - times) % n;
return toRotate;
}
static int querytype2( int toRotate, int times, int n)
{
toRotate = (toRotate + times) % n;
return toRotate;
}
static void querytype3( int toRotate, int l, int r,
int [] preSum, int n)
{
l = (l + toRotate + n) % n;
r = (r + toRotate + n) % n;
if (l <= r)
Console.WriteLine(preSum[r + 1] - preSum[l]);
else
Console.WriteLine(preSum[n] + preSum[r + 1]
- preSum[l]);
}
static void wrapper( int [] a, int n)
{
int [] preSum = new int [n + 1];
preSum[0] = 0;
for ( int i = 1; i <= n; i++)
preSum[i] = preSum[i - 1] + a[i - 1];
int toRotate = 0;
toRotate = querytype1(toRotate, 3, n);
querytype3(toRotate, 0, 2, preSum, n);
toRotate = querytype2(toRotate, 1, n);
querytype3(toRotate, 1, 4, preSum, n);
}
public static void Main()
{
int [] arr = { 1, 2, 3, 4, 5 };
int N = arr.Length;
wrapper(arr, N);
}
}
|
Javascript
<script>
function querytype1(toRotate, times, n){
toRotate = (toRotate - times) % n
return toRotate
}
function querytype2(toRotate, times, n){
toRotate = (toRotate + times) % n
return toRotate
}
function querytype3( toRotate, l, r, preSum, n){
l = (l + toRotate + n) % n
r = (r + toRotate + n) % n
if (l <= r)
document.write((preSum[r + 1] - preSum[l]), "</br>" )
else
document.write((preSum[n] + preSum[r + 1] - preSum[l]), "</br>" )
}
function wrapper(a, n){
preSum = new Array(n+1).fill(0)
for (let i = 1; i <= n; i++)
preSum[i] = preSum[i - 1] + a[i - 1]
toRotate = 0
toRotate = querytype1(toRotate, 3, n)
querytype3(toRotate, 0, 2, preSum, n)
toRotate = querytype2(toRotate, 1, n)
querytype3(toRotate, 1, 4, preSum, n);
}
let arr = [ 1, 2, 3, 4, 5 ]
let N = arr.length
wrapper(arr, N)
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)