Open In App

# 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.

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.

Below is the implementation of the above approach.

## C++14

 `// C++ program to find the maximum``// product in a range with updates``#include ``using` `namespace` `std;` `// Function to print the maximum product``// of any pair in the range [L, R]``void` `query1(vector<``int``> arr, ``int` `n, ``int` `L, ``int` `R)``{` `    ``int` `maxProd = 0;` `    ``// Nested loops to iterate through``    ``// all possible pairs in the range``    ``for` `(``int` `i = L; i < R; i++) {``        ``for` `(``int` `j = i + 1; j <= R; j++) {``            ``int` `prod = arr[i] * arr[j];` `            ``// Update the maximum product``            ``// if a larger product is found``            ``if` `(prod > maxProd) {``                ``maxProd = prod;``            ``}``        ``}``    ``}``    ``// Print the maximum product``    ``// found in the range [L, R]``    ``cout << ``"Maximum product in the range "` `<< L << ``" and "``         ``<< R << ``" is "` `<< maxProd << endl;``}` `// Function to update the value``// of arr[i] to val``void` `query2(vector<``int``>& arr, ``int` `i, ``int` `val)``{``    ``arr[i] = val;``}` `int` `main()``{` `    ``vector<``int``> arr = { 1, 3, 4, 2, 5 };``    ``int` `n = arr.size();` `    ``// Query 1: Print the maximum product``    ``// in the range [L, R]``    ``query1(arr, n, 0, 2);` `    ``// Query 2: Update the value of``    ``// arr[i] to val``    ``query2(arr, 1, 6);` `    ``// Query 3: Print the maximum product``    ``// in the updated range [L, R]``    ``query1(arr, n, 0, 2);` `    ``return` `0;``}`

## Java

 `import` `java.util.Arrays;` `public` `class` `MaxProductRange {` `    ``// Function to print the maximum product of any pair in the range [L, R]``    ``static` `void` `query1(``int``[] arr, ``int` `L, ``int` `R) {``        ``int` `maxProd = ``0``;` `        ``// Nested loops to iterate through all possible pairs in the range``        ``for` `(``int` `i = L; i < R; i++) {``            ``for` `(``int` `j = i + ``1``; j <= R; j++) {``                ``int` `prod = arr[i] * arr[j];` `                ``// Update the maximum product if a larger product is found``                ``if` `(prod > maxProd) {``                    ``maxProd = prod;``                ``}``            ``}``        ``}``        ``System.out.println(``"Maximum product in the range "` `+ L + ``" and "` `+ R + ``" is "` `+ maxProd);``    ``}` `    ``// Function to update the value of arr[i] to val``    ``static` `void` `query2(``int``[] arr, ``int` `i, ``int` `val) {``        ``arr[i] = val;``    ``}``    ``// Driver Code``    ``public` `static` `void` `main(String[] args) {``        ``int``[] arr = {``1``, ``3``, ``4``, ``2``, ``5``};``        ``int` `n = arr.length;` `         ` `        ``query1(arr, ``0``, ``2``);``        ``query2(arr, ``1``, ``6``);``        ``query1(arr, ``0``, ``2``);``    ``}``}`

## Python3

 `# Python program to find the maximum``# product in a range with updates` `# Function to print the maximum product``# of any pair in the range [L, R]``def` `query1(arr, n, L, R):``    ``maxProd ``=` `0` `    ``# Nested loops to iterate through``    ``# all possible pairs in the range``    ``for` `i ``in` `range``(L, R):``        ``for` `j ``in` `range``(i ``+` `1``, R ``+` `1``):``            ``prod ``=` `arr[i] ``*` `arr[j]` `            ``# Update the maximum product``            ``# if a larger product is found``            ``if` `prod > maxProd:``                ``maxProd ``=` `prod` `    ``# Print the maximum product``    ``# found in the range [L, R]``    ``print``(f``"Maximum product in the range {L} and {R} is {maxProd}"``)` `# Function to update the value``# of arr[i] to val``def` `query2(arr, i, val):``    ``arr[i] ``=` `val` `if` `__name__ ``=``=` `"__main__"``:``    ``arr ``=` `[``1``, ``3``, ``4``, ``2``, ``5``]``    ``n ``=` `len``(arr)` `    ``# Query 1: Print the maximum product``    ``# in the range [L, R]``    ``query1(arr, n, ``0``, ``2``)` `    ``# Query 2: Update the value of``    ``# arr[i] to val``    ``query2(arr, ``1``, ``6``)` `    ``# Query 3: Print the maximum product``    ``# in the updated range [L, R]``    ``query1(arr, n, ``0``, ``2``)`

## C#

 `using` `System;``using` `System.Collections.Generic;` `class` `GFG``{``    ``// Function to print the maximum product``    ``// of any pair in the range [L, R]``    ``static` `void` `Query1(List<``int``> arr, ``int` `L, ``int` `R)``    ``{``        ``int` `maxProd = 0;` `        ``// Nested loops to iterate through``        ``// all possible pairs in the range``        ``for` `(``int` `i = L; i < R; i++)``        ``{``            ``for` `(``int` `j = i + 1; j <= R; j++)``            ``{``                ``int` `prod = arr[i] * arr[j];` `                ``// Update the maximum product``                ``// if a larger product is found``                ``if` `(prod > maxProd)``                ``{``                    ``maxProd = prod;``                ``}``            ``}``        ``}``        ``// Print the maximum product``        ``// found in the range [L, R]``        ``Console.WriteLine(\$``"Maximum product in the range {L} and {R} is {maxProd}"``);``    ``}` `    ``// Function to update the value``    ``// of arr[i] to val``    ``static` `void` `Query2(List<``int``> arr, ``int` `i, ``int` `val)``    ``{``        ``arr[i] = val;``    ``}``//Driver code``    ``static` `void` `Main(``string``[] args)``    ``{``        ``List<``int``> arr = ``new` `List<``int``> { 1, 3, 4, 2, 5 };``        ``int` `n = arr.Count;` `        ` `        ``Query1(arr, 0, 2);` `        ` `        ``Query2(arr, 1, 6);` `        ` `        ``Query1(arr, 0, 2);``    ``}``}`

Output

```Maximum product in the range 0 and 2 is 12
Maximum product in the range 0 and 2 is 24

```

Time Complexity: O(N^2) for every query to print the maximum product of any pair and O(1) for updation of the value.
Space Complexity: O(1), no extra space is used.

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++

 `// C++ program to find the maximum``// product in a range with updates``#include& lt; bits / stdc++.h & gt;``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 & gt; e || qe & lt; s || s & gt; e) {` `        ``return` `res;``    ``}` `    ``// complete overlap case``    ``if` `(s& gt; = qs & amp; & e& lt; = 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 & lt; s || i & gt; 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 & gt; 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& lt;``    ``<``    ``"``    ``Maximum product in the range& quot;``    ``<``    ``<``    ``"``    ``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& lt;``    ``<``    ``"``    ``\nMaximum product in the range& quot;``    ``<``    ``<``    ``"``    ``0 and 2 after update : "``    ``<``    ``<``    ``(res.l * res.sl);` `    ``return` `0;``}`

## Java

 `// Java program to find the maximum``// product in a range with updates` `import` `java.util.*;` `public` `class` `Main {``    ``// structure defined``    ``static` `class` `Segment {``        ``// l for largest``        ``// sl for second largest``        ``long` `l;``        ``long` `sl;``    ``}``    ``// function to perform queries``    ``static` `Segment query(Segment[] tree, ``int` `index, ``int` `s,``                         ``int` `e, ``int` `qs, ``int` `qe)``    ``{``        ``Segment res = ``new` `Segment();``        ``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];``        ``}` `        ``int` `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)``        ``long` `largest = Math.max(left.l, right.l);``        ``// compute second largest``        ``// second largest will be minimum``        ``// of maximum from left and right node``        ``long` `second_largest``            ``= Math.min(Math.max(left.l, right.sl),``                       ``Math.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``    ``static` `void` `update(Segment[] tree, ``int` `index, ``int` `s,``                       ``int` `e, ``int` `i, ``int` `val)``    ``{``        ``// no overlapping case``        ``if` `(i < s || i > e) {``            ``return``;``        ``}``        ``// reached leaf node``        ``if` `(s == e) {``            ``tree[index].l = val;``            ``tree[index].sl = Integer.MIN_VALUE;``            ``return``;``        ``}` `        ``int` `mid = (s + e) / ``2``;``        ``// partial overlap``        ``update(tree, ``2` `* index, s, mid, i, val);``        ``update(tree, ``2` `* index + ``1``, mid + ``1``, e, i, val);` `        ``tree[index].l = Math.max(tree[``2` `* index].l,``                                 ``tree[``2` `* index + ``1``].l);` `        ``tree[index].sl``            ``= Math.min(Math.max(tree[``2` `* index].l,``                                ``tree[``2` `* index + ``1``].sl),``                       ``Math.max(tree[``2` `* index + ``1``].l,``                                ``tree[``2` `* index].sl));``    ``}``    ``// Function to build the tree``    ``static` `void` `buildtree(Segment[] tree, ``int``[] a,``                          ``int` `index, ``int` `s, ``int` `e)``    ``{``        ``if` `(s > e) {``            ``return``;``        ``}` `        ``if` `(s == e) {``            ``tree[index].l = a[s];``            ``tree[index].sl = Integer.MIN_VALUE;``            ``return``;``        ``}` `        ``int` `mid = (s + e) / ``2``;` `        ``buildtree(tree, a, ``2` `* index, s, mid);``        ``buildtree(tree, a, ``2` `* index + ``1``, mid + ``1``, e);` `        ``long` `largest = Math.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``        ``long` `second_largest``            ``= Math.min(Math.max(tree[``2` `* index].l,``                                ``tree[``2` `* index + ``1``].sl),``                       ``Math.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` `    ``public` `static` `void` `main(String[] args)``    ``{` `        ``int` `n = ``5``;` `        ``int``[] a = ``new` `int``[] { ``1``, ``3``, ``4``, ``2``, ``5` `};` `        ``// allocating memory for segment tree``        ``Segment[] tree = ``new` `Segment[``4` `* n + ``1``];` `        ``// initializing segment tree nodes``        ``for` `(``int` `i = ``0``; i < ``4` `* n + ``1``; i++) {``            ``tree[i] = ``new` `Segment();``        ``}` `        ``// building segment tree``        ``buildtree(tree, a, ``1``, ``0``, n - ``1``);` `        ``// query section``        ``// storing the resulting node``        ``Segment res = query(tree, ``1``, ``0``, n - ``1``, ``0``, ``2``);` `        ``System.out.println(``"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``);` `        ``System.out.println(``"\nMaximum product in the range "``                           ``+ ``"0 and 2 after update: "``                           ``+ (res.l * res.sl));``    ``}``} ``// function to update the query// Function to build the``  ``// tree`

## Python3

 `# Python code implementation for the above approach.``INT_MAX ``=` `2147483647``INT_MIN ``=` `-``2147483648``# structure defined`  `class` `segment:``     ``# l for largest``     ``# sl for second largest``    ``def` `__init__(``self``, l, sl):``        ``self``.l ``=` `l``        ``self``.sl ``=` `sl` ` ``# function to perform queries`  `def` `query(tree, index, s, e,  qs, qe):` `    ``res ``=` `segment(``0``, ``0``)``    ``res.l ``=` `-``1``    ``res.sl ``=` `-``1``    ``# no overlapping case``    ``if` `qs > e ``or` `qe < s ``or` `s > e:``        ``return` `res` `     ``# complete overlap case``    ``if` `s >``=` `qs ``and` `e <``=` `qe:``        ``return` `tree[index]` `     ``# partial overlap case``    ``mid ``=` `(s ``+` `e) ``/``/` `2` `    ``# calling left node and right node``    ``left ``=` `query(tree, ``2` `*` `index, s, mid, qs, qe)``    ``right ``=` `query(tree, ``2` `*` `index ``+` `1``, mid ``+` `1``, e, qs, qe)` `    ``# largest of ( left.l, right.l)``    ``largest ``=` `max``(left.l, right.l)` `    ``# compute second largest``    ``# second largest will be minimum``    ``# of maximum from left and right node``    ``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`  `def` `update(tree, index, s, e, i, val):` `    ``# no overlapping case``    ``if` `i < s ``or` `i > e:``        ``return` `    ``# reached leaf node``    ``if` `s ``=``=` `e:``        ``tree[index].l ``=` `val``        ``tree[index].sl ``=` `INT_MIN``        ``return` `    ``# partial overlap``    ``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`  `def` `buildtree(tree, a, index, s, 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` `    ``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)``    ``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``    ``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``# your code goes here``n ``=` `5` `a ``=` `[``1``, ``3``, ``4``, ``2``, ``5``]` `# allocating memory for segment tree``tree ``=` `[``0``]``*``(``4``*``n ``+` `1``)``for` `i ``in` `range``(``4``*``n ``+` `1``):``    ``tree[i] ``=` `segment(``0``, ``0``)` ` ``# buildtree(tree, a, index, start, end)``buildtree(tree, a, ``1``, ``0``, n ``-` `1``)` `# query section``# storing the resulting node``res ``=` `query(tree, ``1``, ``0``, n ``-` `1``, ``0``, ``2``)``print``(``"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``)``print``(``"Maximum product in the range 0 and 2 after update: "``, (res.l ``*` `res.sl))` `# The code is contributed by Nidhi goel.`

## C#

 `using` `System;` `class` `Program {``    ``static` `int` `INT_MAX = 2147483647;``    ``static` `int` `INT_MIN = -2147483648;``    ``// structure defined``    ``class` `segment {``        ``// l for largest``        ``// sl for second largest``        ``public` `int` `l;``        ``public` `int` `sl;` `        ``public` `segment(``int` `l, ``int` `sl)``        ``{``            ``this``.l = l;``            ``this``.sl = sl;``        ``}``    ``}``    ``// function to perform queries``    ``static` `segment query(segment[] tree, ``int` `index, ``int` `s,``                         ``int` `e, ``int` `qs, ``int` `qe)``    ``{``        ``segment res = ``new` `segment(0, 0);``        ``res.l = -1;``        ``res.sl = -1;``        ``// no overlapping case``        ``if` `(qs > e || qe < s || s > e) {``            ``return` `res;``        ``}` `        ``if` `(s >= qs && e <= qe) {``            ``return` `tree[index];``        ``}``        ``// partial overlap case``        ``int` `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)``        ``int` `largest = Math.Max(left.l, right.l);``        ``// compute second largest``        ``// second largest will be minimum``        ``// of maximum from left and right node``        ``int` `second_largest``            ``= Math.Min(Math.Max(left.l, right.sl),``                       ``Math.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``    ``static` `void` `update(segment[] tree, ``int` `index, ``int` `s,``                       ``int` `e, ``int` `i, ``int` `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``;``        ``}` `        ``int` `mid = (s + e) / 2;``        ``// partial overlap``        ``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 = Math.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``            ``= Math.Min(Math.Max(tree[2 * index].l,``                                ``tree[2 * index + 1].sl),``                       ``Math.Max(tree[2 * index + 1].l,``                                ``tree[2 * index].sl));``    ``}``    ``// Function to build the tree``    ``static` `void` `buildtree(segment[] tree, ``int``[] a,``                          ``int` `index, ``int` `s, ``int` `e)``    ``{``        ``// tree is build bottom to up``        ``if` `(s > e) {``            ``return``;``        ``}` `        ``if` `(s == e) {``            ``tree[index].l = a[s];``            ``tree[index].sl = INT_MIN;``            ``return``;``        ``}` `        ``int` `mid = (s + e) / 2;``        ``// tree is build bottom to up``        ``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)``        ``int` `largest = Math.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``        ``int` `second_largest``            ``= Math.Min(Math.Max(tree[2 * index].l,``                                ``tree[2 * index + 1].sl),``                       ``Math.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``    ``// your code goes here``    ``static` `void` `Main(``string``[] args)``    ``{``        ``int` `n = 5;``        ``int``[] a = { 1, 3, 4, 2, 5 };` `        ``// allocating memory for segment tree``        ``segment[] tree = ``new` `segment[4 * n + 1];``        ``for` `(``int` `i = 0; i < 4 * n + 1; i++) {``            ``tree[i] = ``new` `segment(0, 0);``        ``}` `        ``// 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);``        ``Console.WriteLine(``            ``"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);``        ``Console.WriteLine(``            ``"Maximum product in the range 0 and 2 after update: "``            ``+ (res.l * res.sl));``    ``}``}`

## Javascript

 `// structure defined``class segment {``    ``// l for largest``    ``// sl for second largest``    ``constructor(l, sl){``        ``this``.l = l;``        ``this``.sl = sl;``    ``}``}``  ` `// function to perform queries``function` `query(tree, index, s, e,  qs, qe)``{``  ` `    ``let res = ``new` `segment();``    ``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``    ``let mid = Math.floor((s + e) / 2);``  ` `    ``// calling left node and right node``    ``let left = query(tree, 2 * index,``                         ``s, mid, qs, qe);``    ``let right = query(tree, 2 * index + 1,``                          ``mid + 1, e, qs, qe);``  ` `    ``// largest of ( left.l, right.l)``    ``let largest = Math.max(left.l, right.l);``  ` `    ``// compute second largest``    ``// second largest will be minimum``    ``// of maximum from left and right node``    ``let second_largest = Math.min(Math.max(left.l, right.sl), Math.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``function` `update(tree, index, s, e, i, val)``{``    ``// no overlapping case``    ``if` `(i < s || i > e) {``        ``return``;``    ``}``  ` `    ``// reached leaf node``  ` `    ``if` `(s == e) {``        ``tree[index].l = val;``        ``tree[index].sl = Number.MIN_VALUE;``        ``return``;``    ``}``  ` `    ``// partial overlap``  ` `    ``let mid = Math.floor((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 = Math.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 = Math.min(Math.max(tree[2 * index].l, tree[2 * index + 1].sl), Math.max(tree[2 * index + 1].l, tree[2 * index].sl));``}``  ` `// Function to build the tree``function` `buildtree(tree, a, index, s, e)``{``    ``// tree is build bottom to up``    ``if` `(s > e) {``        ``return``;``    ``}``  ` `    ``// leaf node``    ``if` `(s == e) {``        ``tree[index].l = a[s];``        ``tree[index].sl = Number.MIN_VALUE;``        ``return``;``    ``}``  ` `    ``let mid = Math.floor((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)``    ``let largest = Math.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``    ``let second_largest = Math.min(Math.max(tree[2 * index].l, tree[2 * index + 1].sl), Math.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``// your code goes here``let n = 5;` `let a = [ 1, 3, 4, 2, 5 ];` `// allocating memory for segment tree``let tree = ``new` `Array(4*n + 1);``for``(let i = 0; i < 4*n + 1; i++){``    ``tree[i] = ``new` `segment();``}` `// buildtree(tree, a, index, start, end)``buildtree(tree, a, 1, 0, n - 1);` `// query section``// storing the resulting node``let res = query(tree, 1, 0, n - 1, 0, 2);``console.log(``"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);``console.log(``"Maximum product in the range 0 and 2 after update: "``, (res.l * res.sl));` `// The code is contributed by Nidhi goel.`

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