# Queries to find maximum product pair in range with updates

• Difficulty Level : Hard
• Last Updated : 11 Jul, 2022

Given an array of N positive integers. The task is to perform the following operations according to the type of query given.
1. Print the maximum pair product in a given range. [L-R]
2. Update Ai with some given value.
Examples:

Input: A={1, 3, 4, 2, 5}
Queries:
Type 1: L = 0, R = 2.
Type 2: i = 1, val = 6
Type 1: L = 0, R = 2.
Output:
12
24
For the query1, the maximum product in a range [0, 2] is 3*4 = 12.
For the query2, after an update, the array becomes [1, 6, 4, 2, 5]
For the query3, the maximum product in a range [0, 2] is 6*4 = 24.

Naive Solution: The brute force approach is to traverse from L to R and check for every pair and then find the maximum product pair among them.
Time Complexity: O(N^2) for every query.
A better solution is to find the first and the second largest number in the range L to R by traversing and then returning their product.
Time Complexity: O(N) for every query.
A efficient solution is to use a segment tree to store the largest and second largest number in the nodes and then return the product of them.
Below is the implementation of above approach.

## CPP

 `// C++ program to find the maximum``// product in a range with updates``#include ``using` `namespace` `std;``#define ll long long`` ` `// structure defined``struct` `segment {``    ``// l for largest``    ``// sl for second largest``    ``ll l;``    ``ll sl;``};`` ` `// function to perform queries``segment query(segment* tree, ll index,``              ``ll s, ll e, ll qs, ll qe)``{`` ` `    ``segment res;``    ``res.l = -1;``    ``res.sl = -1;``    ``// no overlapping case``    ``if` `(qs > e || qe < s || s > e) {`` ` `        ``return` `res;``    ``}`` ` `    ``// complete overlap case``    ``if` `(s >= qs && e <= qe) {`` ` `        ``return` `tree[index];``    ``}`` ` `    ``// partial overlap case``    ``ll mid = (s + e) / 2;`` ` `    ``// calling left node and right node``    ``segment left = query(tree, 2 * index,``                         ``s, mid, qs, qe);``    ``segment right = query(tree, 2 * index + 1,``                          ``mid + 1, e, qs, qe);`` ` `    ``// largest of ( left.l, right.l)``    ``ll largest = max(left.l, right.l);`` ` `    ``// compute second largest``    ``// second largest will be minimum``    ``// of maximum from left and right node``    ``ll second_largest = min(max(left.l, right.sl),``                            ``max(right.l, left.sl));`` ` `    ``// store largest and``    ``// second_largest in res``    ``res.l = largest;``    ``res.sl = second_largest;`` ` `    ``// return the resulting node``    ``return` `res;``}`` ` `// function to update the query``void` `update(segment* tree, ll index,``            ``ll s, ll e, ll i, ll val)``{``    ``// no overlapping case``    ``if` `(i < s || i > e) {``        ``return``;``    ``}`` ` `    ``// reached leaf node`` ` `    ``if` `(s == e) {``        ``tree[index].l = val;``        ``tree[index].sl = INT_MIN;``        ``return``;``    ``}`` ` `    ``// partial overlap`` ` `    ``ll mid = (s + e) / 2;`` ` `    ``// left subtree call``    ``update(tree, 2 * index, s, mid, i, val);`` ` `    ``// right subtree call``    ``update(tree, 2 * index + 1, mid + 1, e, i, val);`` ` `    ``// largest of ( left.l, right.l)``    ``tree[index].l = max(tree[2 * index].l, tree[2 * index + 1].l);`` ` `    ``// compute second largest``    ``// second largest will be``    ``// minimum of maximum from left and right node`` ` `    ``tree[index].sl = min(max(tree[2 * index].l, tree[2 * index + 1].sl),``                         ``max(tree[2 * index + 1].l, tree[2 * index].sl));``}`` ` `// Function to build the tree``void` `buildtree(segment* tree, ll* a, ll index, ll s, ll e)``{``    ``// tree is build bottom to up``    ``if` `(s > e) {``        ``return``;``    ``}`` ` `    ``// leaf node``    ``if` `(s == e) {``        ``tree[index].l = a[s];``        ``tree[index].sl = INT_MIN;``        ``return``;``    ``}`` ` `    ``ll mid = (s + e) / 2;`` ` `    ``// calling the left node``    ``buildtree(tree, a, 2 * index, s, mid);`` ` `    ``// calling the right node``    ``buildtree(tree, a, 2 * index + 1, mid + 1, e);`` ` `    ``// largest of ( left.l, right.l)``    ``ll largest = max(tree[2 * index].l, tree[2 * index + 1].l);`` ` `    ``// compute second largest``    ``// second largest will be minimum``    ``// of maximum from left and right node``    ``ll second_largest = min(max(tree[2 * index].l, tree[2 * index + 1].sl),``                            ``max(tree[2 * index + 1].l, tree[2 * index].sl));`` ` `    ``// storing the largest and``    ``// second_largest values in the current node``    ``tree[index].l = largest;``    ``tree[index].sl = second_largest;``}`` ` `// Driver Code``int` `main()``{`` ` `    ``// your code goes here``    ``ll n = 5;`` ` `    ``ll a = { 1, 3, 4, 2, 5 };`` ` `    ``// allocating memory for segment tree``    ``segment* tree = ``new` `segment[4 * n + 1];`` ` `    ``// buildtree(tree, a, index, start, end)``    ``buildtree(tree, a, 1, 0, n - 1);`` ` `    ``// query section``    ``// storing the resulting node``    ``segment res = query(tree, 1, 0, n - 1, 0, 2);`` ` `    ``cout << ``"Maximum product in the range "``         ``<< ``"0 and 2 before update: "` `<< (res.l * res.sl);`` ` `    ``// update section``    ``// update(tree, index, start, end, i, v)``    ``update(tree, 1, 0, n - 1, 1, 6);`` ` `    ``res = query(tree, 1, 0, n - 1, 0, 2);`` ` `    ``cout << ``"\nMaximum product in the range "``         ``<< ``"0 and 2 after update: "` `<< (res.l * res.sl);`` ` `    ``return` `0;``}`

Output:

```Maximum product in the range 0 and 2 before update: 12
Maximum product in the range 0 and 2 after update: 24```

Time Complexity: O(log N) per query and O(N) for building the tree.

Related Topic: Segment Tree

My Personal Notes arrow_drop_up