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++ program to find the maximum
// product in a range with updates
#include <bits/stdc++.h>
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;
}




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);
    }
}




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




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);
    }
}




// Function to find the maximum
// product in a range with updates
function query1(arr, L, R) {
    let maxProd = 0;
 
    // Nested loops to iterate through
    // all possible pairs in the range
    for (let i = L; i < R; i++) {
        for (let j = i + 1; j <= R; j++) {
            const 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.log(`Maximum product in the range ${L} and ${R} is ${maxProd}`);
}
 
// Function to update the value
// of arr[i] to val
function query2(arr, i, val) {
    arr[i] = val;
}
 
// Driver Code
const arr = [1, 3, 4, 2, 5];
 
// Query 1: Print the maximum product
// in the range [L, R]
query1(arr, 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, 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++ 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 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




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




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));
    }
}




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


Article Tags :