Maximize the summation of numbers in a maximum of K moves in range [L, R] in C++


We are given an array Arr[] containing integers and 2D array Q containing queries. Each query contains 3 values that are lpos, rpos and K. One can move from index i to next index i+1 in a single step or remain in that index. One can move from lpos to rpos in a maximum of K steps only. Add all numbers at each step including the leftmost number. The goal is to maximize the sum in maximum K moves. If no movement is possible from lpos to rpos in K steps then print “No”. Let us understand more.

Let us see various input output scenarios for this -

In − Arr[] = {1, 2, 4, -1 };

Q[][3] = { { 0, 2, 2 }, { 0, 2, 1 }, { 3, 3, 1 }, { 0, 2, 3} };

Out 

Query 1: 7

Query 2: NO

Query 3: NO

Query 4: 11

Explanation 

First Query:-

We can move from index 0 to 2 in max 2 steps:-

Step 1:- index 0 to 1 ( 1+2=3 )

Step 2:- index 1 to 2 ( 3+4=7 )

Second Query:-

We cannot move from index 0 to 2 in max 1 step. Print “NO”

Third Query:-

We cannot move from index 3 to 3 in max 1 step. Print “NO”

Fourth Query:-

We can move from index 0 to 2 in max 3 steps:-

Step 1:- index 0 to 1 ( 1+2=3 )

Step 2:- index 1 to 2 ( 3+4=7 )

Step 3:- Stay at index 2 ( 7+4=11 )

In − Arr[] = { 1, 2, 3, 3, 2 }; Q[][3] = { { 0, 3, 2 }, { 1, 4, 3 } };

Out 

Query 1: NO

Query 2: 10

Explanation 

First Query:-

We cannot move from index 0 to 2 in max 1 step. Print “NO”

Second Query:-

We can move from index 1 to 4 in max 3 steps:-

Step 1:- index 1 to 2 ( 2+3=5 )

Step 2:- index 2 to 3 ( 5+3=8 )

Step 3:- index 3 to 4 ( 8+2=10 )

Approach used in the below program is as follows

In this approach we will use segment tree for the range lpos to rpos to find the maximum value possible and calculate summation of all numbers using prefix sum.

  • Take input array Arr[] and query matrix Q[][].

  • Take sgTreee[5 * length] as array for implementing segment tree.

  • Take pSum[length] as prefix sum array.

  • Function createTree(int min, int max, int pos, int sgT[], int arr[], int len) is used to create values in a segment tree.

  • Check if (min == max) which means it is a leaf node. Set sgT[pos] = arr[max].

  • Take midd = (min + max) / 2.

  • Call createTree(min, midd, loc1, sgT, arr, len) and createTree(midd + 1, max, loc2, sgT, arr, len) for left and right subtrees where loc1=2*pos+1 and loc2=2*pos+2.

  • Take tmp1=sgT[loc1] and tmp2=sgT[loc2] and update sgT[pos] with tmp1 or tmp2 whichever is maximum.

  • Function preSum(int pSum4[], int arr4[], int len4) takes the input array and updates the prefix array using for loop.

  • For every element from index 1 to last, update pSum4[j] = pSum4[j - 1] + arr4[j];

  • Function resQuery(int len3, int arr3[], int sgT3[], int pSum3[], int q1[][3], int qlen1) takes all input parameters and prints the result for each query.

  • Inside resQuery(), call solQuery(int lpos, int rpos, int k, int len2, int arr2[], int sgT2[], int pSum2[]) to solve each query one by one using for loop.

  • Function solQuery(int lpos, int rpos, int k, int len2, int arr2[], int sgT2[], int pSum2[]) solves the query and returns the result.

  • If rpos - lpos > k then return -1 as no solution is possible.

  • Take maxVal = findMax(0, len2 - 1, lpos, rpos, 0, sgT2, arr2, len2);

  • If maxVal < 0 then set maxVal as 0

  • Take variable sum = pSum2[rpos].

  • If lpos > 0 then set sum -= pSum2[lpos - 1] and result = sum + (k - (rpos - lpos)) * maxVal.

  • Return result.

  • Function findMax(int start, int end, int min1, int max1, int pos1, int sgT1[], int arr1[], int len1) returns the maximum value between range lpos and rpos.

  • If (min1 <= start) and ( max1 >= end) then return sgT1[pos1] as there is an overlap.

  • If (end < min1 || start > max1) then there is out of range occurring so return INT_MIN.

  • Calculate lmax and rmax using recursive calls for left and right subtree and return maximum of two.

  • At the end the result will be printed for each query. “No” if there is no solution

Example

#include <bits/stdc++.h>
using namespace std;
void createTree(int min, int max, int pos,
int sgT[], int arr[], int len){ if (min == max) {
   sgT[pos] = arr[max];
   return;
   }
   int midd = (min + max) / 2;
   int loc1=2*pos+1;
   int loc2=2*pos+2;
   createTree(min, midd, loc1, sgT, arr, len);
   createTree(midd + 1, max, loc2, sgT, arr, len);
   int tmp1=sgT[loc1];
   int tmp2=sgT[loc2];
   sgT[pos] = tmp1>tmp2 ? tmp1 : tmp2 ;
}
int findMax(int start, int end, int min1, int max1, int pos1, int sgT1[], int arr1[], int len1){
   int middle;
   if (min1 <= start)
   { if( max1 >= end){
         return sgT1[pos1];
      }
   }
   if (end < min1 || start > max1)
   { return INT_MIN; }

   middle = (start + end) / 2;
   int loc1=2 * pos1 + 1;
   int loc2=2 * pos1 + 2;
   int lmax = findMax(start, middle, min1, max1, loc1, sgT1, arr1, len1);
   int rmax = findMax(middle + 1, end, min1, max1, loc2, sgT1, arr1, len1);
   int res=lmax>rmax?lmax:rmax;
   return res;
}
int solQuery(int lpos, int rpos, int k, int len2, int arr2[], int sgT2[], int pSum2[]){
   int result;
      if (rpos - lpos > k)
      { return -1; }
      int maxVal = findMax(0, len2 - 1, lpos, rpos, 0, sgT2, arr2, len2);
      if (maxVal < 0)
      { maxVal = 0; }
      int sum = pSum2[rpos];
      if (lpos > 0)
      { sum -= pSum2[lpos - 1]; }
      result = sum + (k - (rpos - lpos)) * maxVal;
      return result;
   }
   void resQuery(int len3, int arr3[], int sgT3[],
         int pSum3[], int q1[][3], int qlen1){
      int i;
      int result;
      for (i = 0; i < qlen1; i++) {
      result = solQuery(q1[i][0], q1[i][1],q1[i][2], len3, arr3, sgT3, pSum3);

      if (result == -1)
         { cout <<endl<<"Query "<<i+1<<": "<<"NO"; }
      else
         { cout <<endl<<"Query "<<i+1<<": "<<result; }
      }
   }
void preSum(int pSum4[], int arr4[], int len4){
   pSum4[0] = arr4[0];
   int j;
   for (j = 1; j < len4; j++){
      pSum4[j] = pSum4[j - 1] + arr4[j];
   }
}
int main(){
   int Arr[] = {1, 2, 4, -1 };
   int length = sizeof(Arr) / sizeof(Arr[0]);
   int sgTreee[5 * length];
   createTree(0, length - 1, 0, sgTreee, Arr, length);
   int pSum[length];
   preSum(pSum, Arr, length);
   int Q[][3] = { { 0, 2, 2 },
      { 0, 2, 1 },
      { 3, 3, 1 },
      { 0, 2, 3} };
   int qlen = sizeof(Q) / sizeof(Q[0]);
   resQuery(length, Arr, sgTreee, pSum, Q, qlen);
   return 0;
}

Output

If we run the above code it will generate the following Output

Query 1: 7
Query 2: NO
Query 3: NO
Query 4: 11

Updated on: 22-Oct-2021

79 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements