# Queries to find maximum product pair in range with updates

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.

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

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.

 `// 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; ` `} ` ` `  `// funcntion 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[5] = { 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.

My Personal Notes arrow_drop_up

Maths is the language of nature

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.