Queries to find maximum product pair in range with updates in C++


In this problem, we are given an array arr[] and Q queries. Each Query can be one of 2 types, 1st to find the maximum pair product in a given range [ Start - End ]. 2nd to update the ith index element with value. Our task is to create a program to solve Queries to find maximum product pair in range with updates in C++.

Let’s take an example to understand the problem,

Input:arr = {4, 2, 6, 9, 1}

Q = 3

Q1 = [1, 1, 4]

Q2 = [2, 2, 3]

Q3 = [1, 0, 2]

Output: 54, 12

Explanation

For query 1, type 1: range = {2, 6, 9, 1}. Maximum product 6*9 = 54

For query 2, type 2: i = 2 , updated array arr[] = {4, 2, 3, 9, 1}

For query 3, type 1: range = {4, 2, 3}. Maximum product 4*3 = 12

Solution Approach

To solve the problem, we have a simple approach. Which is for every query of type one traverse the whole array and check every pair’s product and then find the maximum product pair amongst them.

Example

 Live Demo

#include <iostream>
using namespace std;
int max(int a, int b){
   if(a>b)
      return a;
      return b;
}
int findMaxProductPair(int arr[], int n, int start, int end){
   int maxProd = 0;
   for(int i = start; i <= end; i++){
      for(int j = i+1; j <= end; j++){
         maxProd = max(maxProd, (arr[i]*arr[j]));
      }
   }
   return maxProd;
}
int main(){
   int arr[] = {4, 2, 6, 9, 1, 5};
   int n = 6;
   int Q = 3;
   int query[Q][3] = {{1, 1, 4}, {2, 2, 3}, {1, 0, 2}};
   for(int i = 0; i < Q; i++){
      if(query[i][0] == 1){
         cout<<"The maximum product pair in the range is "<<findMaxProductPair(arr, n, query[i][1], query[i][2])<<"\n";
      }
      else if(query[i][0] == 2){
         cout<<"Updating values...\n";
         arr[query[i][1]] = query[i][2];
      }
   }
   return 0;
}

Output

The maximum product pair in the range is 54
Updating values...
The maximum product pair in the range is 12

This approach is good but to find the max product, we need to traverse the whole array that increases the time complexity.

An efficient solution could be using a segment tree data structure to store the two largest elements of the sub-array. And then return their product.

Example

 Live Demo

#include <iostream>
using namespace std;
struct segment {
   int maxEle;
   int secMax;
};
segment findMaxProductPair(segment* prodTree, int index, int start, int end, int L, int R) {
   segment result;
   result.maxEle = -1;
   result.secMax = -1;
   if (L > end || R < start || start > end)
      return result;
   if (start >= L && end <= R)
      return prodTree[index];
   int middleIndex = (start + end) / 2;
   segment left = findMaxProductPair(prodTree, 2 * index, start,middleIndex, L, R);
   segment right = findMaxProductPair(prodTree, 2 * index + 1,middleIndex + 1, end, L, R);
   result.maxEle = max(left.maxEle, right.maxEle);
   result.secMax = min(max(left.maxEle, right.secMax),max(right.maxEle, left.secMax));
   return result;
}
void update(segment* prodTree, int index, int start, int end, int i, intupdateVal) {
   if (i < start || i > end)
      return;
   if (start == end) {
      prodTree[index].maxEle = updateVal;
      prodTree[index].secMax = -1;
      return;
   }
   int middleIndex = (start + end) / 2;
   update(prodTree, 2 * index, start, middleIndex, i, updateVal);
   update(prodTree, 2 * index + 1, middleIndex + 1, end, i, updateVal);
   prodTree[index].maxEle = max(prodTree[2 * index].maxEle,prodTree[2 * index + 1].maxEle);
   prodTree[index].secMax = min(max(prodTree[2 * index].maxEle,prodTree[2 * index + 1].secMax), max(prodTree[2 * index + 1].maxEle,prodTree[2 * index].secMax));
}
void buildtree(segment* prodTree, int* arr, int index, int start, int end) {
   if (start > end) {
      return;
   }
   if (start == end) {
      prodTree[index].maxEle = arr[start];
      prodTree[index].secMax = -1;
      return;
   }
   int middleIndex = (start + end) / 2;
   buildtree(prodTree, arr, 2 * index, start, middleIndex);
   buildtree(prodTree, arr, 2 * index + 1, middleIndex + 1, end);
   int maximum = max(prodTree[2 * index].maxEle, prodTree[2 * index + 1].maxEle);
   int secMaximum = min(max(prodTree[2 * index].maxEle, prodTree[2 * index + 1].secMax),max(prodTree[2 * index + 1].maxEle, prodTree[2 * index].secMax));
   prodTree[index].maxEle = maximum;
   prodTree[index].secMax = secMaximum;
}
int main() {
   int arr[] = {4, 2, 6, 9, 1, 5};
   int n = 6;
   int Q = 3;
   segment* prodTree = new segment[4 * n + 1];
   buildtree(prodTree, arr, 1, 0, n - 1);
   int query[Q][3] = {{1, 1, 4}, {2, 2, 3}, {1, 0, 2}};
   for(int i = 0; i < Q; i++){
      if(query[i][0] == 1){
         segment result = findMaxProductPair(prodTree, 1, 0, n - 1,query[i][1] , query[i][2]);
         cout<<"The maximum product pair in the range is "<<(result.maxEle*result.secMax)<<"\n";
      }
      else if(query[i][0] == 2){
         cout<<"Updating values...\n";
      update(prodTree, 1, 0, n - 1, query[i][1], query[i][2]);
      }
   }
   return 0;
}

Output

The maximum product pair in the range is 54
Updating values...
The maximum product pair in the range is 12

Updated on: 09-Oct-2020

290 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements