Given an array arr[] of N integers and Q queries. Each query consists of 3 integers L, R and K. You can move from index i to index i + 1 in a single step or stay in that particular index in a single step. You can move from L to R index in a maximum of K steps and print the summation of every number you were at in every step including the L-th number. The task is to maximize the summation in a maximum of K moves. If we cannot move from L to R in K steps then print “No”.
Examples:
Input: arr[] = {1, 3, 2, -4, -5}, q = {
{0, 2, 2},
{0, 2, 4},
{3, 4, 1},
{0, 4, 2}}
Output:
6
12
-9
No
For first query:
In first step move from 0th index to 1st index, hence 1 + 3 = 4
In second step move from 1st index to 2nd index, hence 4 + 2 = 6
For second query:
In first step move from 0th index to 1st index, hence 1 + 3 = 4
In second step stay at the 1st index, hence 4 + 3 = 7
In third step again stay at the 1st index, hence 7 + 3 = 10
In fourth step move from 1st index to 2nd index only, hence 10 + 2 = 12
A naive approach is to check first if L – R > K, if it is then we cannot move from L to R index in K steps. Iterate from L to R, get the sum of all elements between L and R. Then find the maximum element in the range L and R and the answer will be the sum of elements in the range and (K – (R – L)) * maximum. If the maximum is a negative number we exactly perform R – L moves else we perform the extra steps at the maximum number index in the range [L, R].
Time Complexity: O(R – L) per query.
An efficient approach is to use segment tree in the range [L, R] to find the maximum number and find the sum in the range using prefix sum.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Function to create the tree void tree( int low, int high, int pos, int b[], int a[], int n) { // Leaf nodes if (low == high) { b[pos] = a[high]; return ; } int mid = (high + low) / 2; // Left subtree tree(low, mid, 2 * pos + 1, b, a, n); // Right subtree tree(mid + 1, high, 2 * pos + 2, b, a, n); // Merge the maximum b[pos] = max(b[2 * pos + 1], b[2 * pos + 2]); } // Function that returns the maximum in range L and R int rangemax( int s, int e, int low, int high, int pos, int b[], int a[], int n) { // Complete overlap if (low <= s && high >= e) return b[pos]; // Out of range completely if (e < low || s > high) return INT_MIN; int mid = (s + e) / 2; // Find maximum in left and right subtrees int left = rangemax(s, mid, low, high, 2 * pos + 1, b, a, n); int right = rangemax(mid + 1, e, low, high, 2 * pos + 2, b, a, n); // Return the maximum of both return max(left, right); } // Function that solves a query int solveQuery( int l, int r, int k, int n, int a[], int b[], int prefix[]) { // If there are ko if (r - l > k) return -1; // Find maximum in range L and R int maximum = rangemax(0, n - 1, l, r, 0, b, a, n); // If maximum is 0 if (maximum < 0) maximum = 0; // Find the prefix sum int rangesum = prefix[r]; // If not first element if (l > 0) rangesum -= prefix[l - 1]; // Get the answer int answer = rangesum + (k - (r - l)) * maximum; return answer; } // Function that solves the queries void solveQueries( int n, int a[], int b[], int prefix[], int queries[][3], int q) { // Solve all the queries for ( int i = 0; i < q; i++) { int ans = solveQuery(queries[i][0], queries[i][1], queries[i][2], n, a, b, prefix); if (ans != -1) cout << ans << endl; else cout << "No" << endl; } } // Function to find the prefix sum void findPrefixSum( int prefix[], int a[], int n) { prefix[0] = a[0]; for ( int i = 1; i < n; i++) { prefix[i] = prefix[i - 1] + a[i]; } } // Driver code int main() { int a[] = { 1, 3, 2, -4, -5 }; int n = sizeof (a) / sizeof (a[0]); // Array for segment tree int b[5 * n]; // Create segment tree tree(0, n - 1, 0, b, a, n); int prefix[n]; // Fill prefix sum array findPrefixSum(prefix, a, n); // Queries int queries[][3] = { { 0, 2, 2 }, { 0, 2, 4 }, { 3, 4, 1 }, { 0, 4, 2 } }; int q = sizeof (queries) / sizeof (queries[0]); solveQueries(n, a, b, prefix, queries, q); return 0; } |
Java
// Java implementation of the approach class GFG { // Function to create the tree static void tree( int low, int high, int pos, int b[], int a[], int n) { // Leaf nodes if (low == high) { b[pos] = a[high]; return ; } int mid = (high + low) / 2 ; // Left subtree tree(low, mid, 2 * pos + 1 , b, a, n); // Right subtree tree(mid + 1 , high, 2 * pos + 2 , b, a, n); // Merge the maximum b[pos] = Math.max(b[ 2 * pos + 1 ], b[ 2 * pos + 2 ]); } // Function that returns the maximum in range L and R static int rangemax( int s, int e, int low, int high, int pos, int b[], int a[], int n) { // Complete overlap if (low <= s && high >= e) return b[pos]; // Out of range completely if (e < low || s > high) return Integer.MIN_VALUE; int mid = (s + e) / 2 ; // Find maximum in left and right subtrees int left = rangemax(s, mid, low, high, 2 * pos + 1 , b, a, n); int right = rangemax(mid + 1 , e, low, high, 2 * pos + 2 , b, a, n); // Return the maximum of both return Math.max(left, right); } // Function that solves a query static int solveQuery( int l, int r, int k, int n, int a[], int b[], int prefix[]) { // If there are ko if (r - l > k) return - 1 ; // Find maximum in range L and R int maximum = rangemax( 0 , n - 1 , l, r, 0 , b, a, n); // If maximum is 0 if (maximum < 0 ) maximum = 0 ; // Find the prefix sum int rangesum = prefix[r]; // If not first element if (l > 0 ) rangesum -= prefix[l - 1 ]; // Get the answer int answer = rangesum + (k - (r - l)) * maximum; return answer; } // Function that solves the queries static void solveQueries( int n, int a[], int b[], int prefix[], int queries[][], int q) { // Solve all the queries for ( int i = 0 ; i < q; i++) { int ans = solveQuery(queries[i][ 0 ], queries[i][ 1 ], queries[i][ 2 ], n, a, b, prefix); if (ans != - 1 ) System.out.println(ans); else System.out.println( "No" ); } } // Function to find the prefix sum static void findPrefixSum( int prefix[], int a[], int n) { prefix[ 0 ] = a[ 0 ]; for ( int i = 1 ; i < n; i++) { prefix[i] = prefix[i - 1 ] + a[i]; } } // Driver code public static void main(String[] args) { int a[] = { 1 , 3 , 2 , - 4 , - 5 }; int n = a.length; // Array for segment tree int b[] = new int [ 5 * n]; // Create segment tree tree( 0 , n - 1 , 0 , b, a, n); int prefix[] = new int [n]; // Fill prefix sum array findPrefixSum(prefix, a, n); // Queries int queries[][] = { { 0 , 2 , 2 }, { 0 , 2 , 4 }, { 3 , 4 , 1 }, { 0 , 4 , 2 } }; int q = queries.length; solveQueries(n, a, b, prefix, queries, q); } } /* This code contributed by PrinciRaj1992 */ |
Python3
# Python3 implementation of the approach # Function to create the tree def tree( low, high, pos, b, a, n): # Leaf nodes if (low = = high): b[pos] = a[high] return mid = (high + low) / / 2 # Left subtree tree(low, mid, 2 * pos + 1 , b, a, n) # Right subtree tree(mid + 1 , high, 2 * pos + 2 , b, a, n) # Merge the maximum b[pos] = max (b[ 2 * pos + 1 ], b[ 2 * pos + 2 ]) # Function that returns the maximum in range L and R def rangemax(s, e, low, high, pos, b, a, n): # Complete overlap if (low < = s and high > = e): return b[pos] # Out of range completely if (e < low or s > high): return - ( 2 * * 32 ) mid = (s + e) / / 2 # Find maximum in left and right subtrees left = rangemax(s, mid, low, high, 2 * pos + 1 , b, a, n) right = rangemax(mid + 1 , e, low, high, 2 * pos + 2 , b, a, n) # Return the maximum of both return max (left, right) # Function that solves a query def solveQuery(l, r, k, n, a, b, prefix): # If there are ko if (r - l > k): return - 1 # Find maximum in range L and R maximum = rangemax( 0 , n - 1 , l, r, 0 , b, a, n) # If maximum is 0 if (maximum < 0 ): maximum = 0 # Find the prefix sum rangesum = prefix[r] # If not first element if (l > 0 ): rangesum - = prefix[l - 1 ] # Get the answer answer = rangesum + (k - (r - l)) * maximum return answer # Function that solves the queries def solveQueries( n, a, b, prefix, queries, q): # Solve all the queries for i in range (q): ans = solveQuery(queries[i][ 0 ], queries[i][ 1 ], queries[i][ 2 ], n, a, b, prefix) if (ans ! = - 1 ): print (ans) else : print ( "No" ) # Function to find the prefix sum def findPrefixSum( prefix, a, n): prefix[ 0 ] = a[ 0 ] for i in range ( 1 , n): prefix[i] = prefix[i - 1 ] + a[i] # Driver code a = [ 1 , 3 , 2 , - 4 , - 5 ] n = len (a) # Array for segment tree b = [ 0 ] * ( 5 * n) # Create segment tree tree( 0 , n - 1 , 0 , b, a, n) prefix = [ 0 ] * n # Fill prefix sum array findPrefixSum(prefix, a, n) # Queries queries = [[ 0 , 2 , 2 ],[ 0 , 2 , 4 ],[ 3 , 4 , 1 ],[ 0 , 4 , 2 ]] q = len (queries) solveQueries(n, a, b, prefix, queries, q) # This code is contributed by SHUBHAMSINGH10 |
C#
// C# program to implement // the above approach using System; class GFG { // Function to create the tree static void tree( int low, int high, int pos, int []b, int []a, int n) { // Leaf nodes if (low == high) { b[pos] = a[high]; return ; } int mid = (high + low) / 2; // Left subtree tree(low, mid, 2 * pos + 1, b, a, n); // Right subtree tree(mid + 1, high, 2 * pos + 2, b, a, n); // Merge the maximum b[pos] = Math.Max(b[2 * pos + 1], b[2 * pos + 2]); } // Function that returns the maximum in range L and R static int rangemax( int s, int e, int low, int high, int pos, int []b, int []a, int n) { // Complete overlap if (low <= s && high >= e) return b[pos]; // Out of range completely if (e < low || s > high) return int .MinValue; int mid = (s + e) / 2; // Find maximum in left and right subtrees int left = rangemax(s, mid, low, high, 2 * pos + 1, b, a, n); int right = rangemax(mid + 1, e, low, high, 2 * pos + 2, b, a, n); // Return the maximum of both return Math.Max(left, right); } // Function that solves a query static int solveQuery( int l, int r, int k, int n, int []a, int []b, int []prefix) { // If there are ko if (r - l > k) return -1; // Find maximum in range L and R int maximum = rangemax(0, n - 1, l, r, 0, b, a, n); // If maximum is 0 if (maximum < 0) maximum = 0; // Find the prefix sum int rangesum = prefix[r]; // If not first element if (l > 0) rangesum -= prefix[l - 1]; // Get the answer int answer = rangesum + (k - (r - l)) * maximum; return answer; } // Function that solves the queries static void solveQueries( int n, int []a, int []b, int []prefix, int [,]queries, int q) { // Solve all the queries for ( int i = 0; i < q; i++) { int ans = solveQuery(queries[i,0], queries[i,1], queries[i,2], n, a, b, prefix); if (ans != -1) Console.WriteLine(ans); else Console.WriteLine( "No" ); } } // Function to find the prefix sum static void findPrefixSum( int []prefix, int []a, int n) { prefix[0] = a[0]; for ( int i = 1; i < n; i++) { prefix[i] = prefix[i - 1] + a[i]; } } // Driver code public static void Main(String[] args) { int []a = { 1, 3, 2, -4, -5 }; int n = a.Length; // Array for segment tree int []b = new int [5 * n]; // Create segment tree tree(0, n - 1, 0, b, a, n); int []prefix = new int [n]; // Fill prefix sum array findPrefixSum(prefix, a, n); // Queries int [,]queries = { { 0, 2, 2 }, { 0, 2, 4 }, { 3, 4, 1 }, { 0, 4, 2 } }; int q = queries.GetLength(0); solveQueries(n, a, b, prefix, queries, q); } } // This code has been contributed by 29AjayKumar |
Javascript
<script> // JavaScript implementation of the approach // Function to create the tree function tree(low,high,pos,b,a,n) { // Leaf nodes if (low == high) { b[pos] = a[high]; return ; } let mid = Math.floor((high + low) / 2); // Left subtree tree(low, mid, 2 * pos + 1, b, a, n); // Right subtree tree(mid + 1, high, 2 * pos + 2, b, a, n); // Merge the maximum b[pos] = Math.max(b[2 * pos + 1], b[2 * pos + 2]); } // Function that returns the maximum in range L and R function rangemax(s,e,low,high,pos,b,a,n) { // Complete overlap if (low <= s && high >= e) return b[pos]; // Out of range completely if (e < low || s > high) return Number.MIN_VALUE; let mid = Math.floor((s + e) / 2); // Find maximum in left and right subtrees let left = rangemax(s, mid, low, high, 2 * pos + 1, b, a, n); let right = rangemax(mid + 1, e, low, high, 2 * pos + 2, b, a, n); // Return the maximum of both return Math.max(left, right); } // Function that solves a query function solveQuery(l,r,k,n,a,b,prefix) { // If there are ko if (r - l > k) return -1; // Find maximum in range L and R let maximum = rangemax(0, n - 1, l, r, 0, b, a, n); // If maximum is 0 if (maximum < 0) maximum = 0; // Find the prefix sum let rangesum = prefix[r]; // If not first element if (l > 0) rangesum -= prefix[l - 1]; // Get the answer let answer = rangesum + (k - (r - l)) * maximum; return answer; } // Function that solves the queries function solveQueries(n,a,b,prefix,queries,q) { // Solve all the queries for (let i = 0; i < q; i++) { let ans = solveQuery(queries[i][0], queries[i][1], queries[i][2], n, a, b, prefix); if (ans != -1) document.write(ans+ "<br>" ); else document.write( "No<br>" ); } } // Function to find the prefix sum function findPrefixSum(prefix,a,n) { prefix[0] = a[0]; for (let i = 1; i < n; i++) { prefix[i] = prefix[i - 1] + a[i]; } } // Driver code let a=[1, 3, 2, -4, -5]; let n = a.length; // Array for segment tree let b = new Array(5 * n); // Create segment tree tree(0, n - 1, 0, b, a, n); let prefix = new Array(n); // Fill prefix sum array findPrefixSum(prefix, a, n); // Queries let queries = [[ 0, 2, 2 ], [ 0, 2, 4 ], [ 3, 4, 1 ], [ 0, 4, 2 ] ]; let q = queries.length; solveQueries(n, a, b, prefix, queries, q); // This code is contributed by rag2127 </script> |
6 12 -9 No
Time Complexity: O(Log N) per query.
Auxiliary Space: O(N log N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!