// JavaScript program to find minimum and maximum using segment
// tree
// A utility function to get the middle index from corner
// indexes.
function getMid(s, e) {
return Math.floor(s + (e - s) / 2);
}
// Node for storing minimum and maximum value of given range
class Node {
constructor(minimum, maximum) {
this.minimum = minimum;
this.maximum = maximum;
}
}
/* A recursive function to get the minimum and maximum
value in a given range of array indexes. The following
are parameters for this function.
st --> Pointer to segment tree
index --> Index of current node in the segment tree.
Initially 0 is passed as root is always at index 0 ss &
se --> Starting and ending indexes of the segment
represented by current node, i.e.,
st[index] qs & qe --> Starting and ending indexes of
query range */
function MaxMinUntill(st, ss, se, qs, qe, index) {
// If segment of this node is a part of given range,
// then return
// the minimum and maximum node of the segment
let tmp, left, right;
if (qs <= ss && qe >= se) {
return st[index];
}
// If segment of this node is outside the given range
if (se < qs || ss > qe) {
tmp = new Node(Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
return tmp;
}
// If a part of this segment overlaps with the given
// range
const mid = getMid(ss, se);
left = MaxMinUntill(st, ss, mid, qs, qe, 2 * index + 1);
right = MaxMinUntill(st, mid + 1, se, qs, qe, 2 * index + 2);
tmp = new Node(Math.min(left.minimum, right.minimum), Math.max(left.maximum, right.maximum));
return tmp;
}
// Return minimum and maximum of elements in range from
// index qs (query start) to qe (query end). It mainly uses
// MaxMinUtill()
function MaxMin(st, n, qs, qe) {
let tmp;
// Check for erroneous input values
if (qs < 0 || qe > n - 1 || qs > qe) {
console.log("Invalid Input");
tmp = new Node(Number.MAX_SAFE_INTEGER, Number.MIN_SAFE_INTEGER);
return tmp;
}
return MaxMinUntill(st, 0, n - 1, qs, qe, 0);
}
// A recursive function that constructs Segment Tree for
// array[ss..se]. si is index of current node in segment
// tree st
function constructSTUtil(arr, ss, se, st, si) {
// If there is one element in array, store it in current
// node of segment tree and return
if (ss == se) {
st[si] = new Node(arr[ss], arr[ss]);
return;
}
// If there are more than one elements, then recur for
// left and right subtrees and store the minimum and
// maximum of two values in this node
var mid = getMid(ss, se);
constructSTUtil(arr, ss, mid, st, si * 2 + 1);
constructSTUtil(arr, mid + 1, se, st, si * 2 + 2);
st[si] = new Node(Math.min(st[si * 2 + 1].minimum, st[si * 2 + 2].minimum), Math.max(st[si * 2 + 1].maximum, st[si * 2 + 2].maximum));
}
/* Function to construct segment tree from given array. This
function allocates memory for segment tree and calls
constructSTUtil() to fill the allocated memory */
function constructST(arr, n) {
// Allocate memory for segment tree
// Height of segment tree
const x = Math.ceil(Math.log2(n));
// Maximum size of segment tree
var max_size = 2 * Math.pow(2, x) - 1;
var st = new Array(max_size).fill(null);
// Fill the allocated memory st
constructSTUtil(arr, 0, n - 1, st, 0);
// Return the constructed segment tree
return st;
}
// Driver code
var arr = [1, 8, 5, 9, 6, 14, 2, 4, 3, 7];
var n = arr.length;
// Build segment tree from given array
var st = constructST(arr, n);
var qs = 0; // Starting index of query range
var qe = 8; // Ending index of query range
var result = MaxMin(st, n, qs, qe);
// Function call
console.log(`Minimum = ${result.minimum} and Maximum = ${result.maximum}`);
// This code is contributed by prasad264