Related Articles
Queries to find the minimum index in a range [L, R] having at least value X with updates
• Difficulty Level : Expert
• Last Updated : 28 Jan, 2021

Given an array arr[] consisting of N integers and an array Queries[] consisting of Q queries of the type {X, L, R} to perform following operations:

• If the value of X is 1, then update the array element at Xth index to L.
• Otherwise, find the minimum index j in the range [L, R] such that arr[j] ≥ X. If no such j exists, then print “-1”.

Examples:

Input: arr[] = {1, 3, 2, 4, 6}, Queries[][] = {{2, 0, 4}, {1, 2, 5}, {4, 0, 4}, {0, 0, 4}}
Output: 1 2 0
Explanation:
Query 1: find(2, 0, 4) => First element which is at least 2 is 3. So, its index is 1.
Query 2: update(2, 5) => arr[] = {1, 3, 5, 4, 6}.
Query 3: find(4, 0, 4) => First element which is at least 4 is 5. So, its index is 2.
Query 4: find(0, 0, 4) => First element which is at least 0 is 1. So, its index is 0.

Input: arr[] = {1}, Queries[][] = {{2, 0, 0}};
Output: 1 2 0
Explanation:
Query 1: find(2, 0, 0) => No element is greater than 2. Therefore, print -1.

Naive Approach: The simplest approach is to traverse the array for each query. For the queries of Type 1, update A[X] to L. For the query of Type 2, traverse the array arr[] over the range [L, R] and find the minimum index j satisfying the condition. If no such index is found, then print “-1”
Time Complexity: O(N*Q)
Auxiliary Space: O(N)

Efficient Approach: To optimize the above approach, the idea is to use Segment Tree in order to perform queries efficiently. Follow the steps below to solve the problem:

• Construct a Segment Tree where each node will represent the maximum value in the range of that node. For example, for any given range [i, j], its corresponding node will contain the maximum value in that range.
• Initialize a variable, say ans.
• Now, for queries of type 2, if the current range does not lie inside the range [L, R], then traverse its left subtree.
• Now, in the left subtree, if the maximum exceeds X and the current range lies inside the range [L, R], then go to the mid-point of that range and check if its value is greater than X or not. If found to be true, visit its left part. Otherwise, visit its right part.
• Update the variable ans as the minimum index between the given range if it exists.
• Continue the above steps, until the left part of the range becomes equal to the right part.
• After completing the above steps, print the value of ans as the result.

Below is the implementation of the above approach:

## C++

 `// C++ program for the above approach``#include ``#define maxN 100``using` `namespace` `std;` `// Stores nodes value of the Tree``int` `Tree[4 * maxN];` `// Function to build segment tree``void` `build(``int` `arr[], ``int` `index,``           ``int` `s, ``int` `e)``{``    ``// Base Case``    ``if` `(s == e)``        ``Tree[index] = arr[s];` `    ``else` `{``        ``// Find the value of mid``        ``int` `m = (s + e) / 2;` `        ``// Update for left subtree``        ``build(arr, 2 * index, s, m);` `        ``// Update for right subtree``        ``build(arr, 2 * index + 1,``              ``m + 1, e);` `        ``// Update the value at the``        ``// current index``        ``Tree[index]``            ``= max(Tree[2 * index],``                  ``Tree[2 * index + 1]);``    ``}``}` `// Function for finding the index``// of the first element at least x``int` `atleast_x(``int` `index, ``int` `s, ``int` `e,``              ``int` `ql, ``int` `qr, ``int` `x)``{``    ``// If current range does``    ``// not lie in query range``    ``if` `(ql > e || qr < s)``        ``return` `-1;` `    ``// If current range is inside``    ``// of query range``    ``if` `(s <= ql && e <= qr) {` `        ``// Maximum value in this``        ``// range is less than x``        ``if` `(Tree[index] < x)``            ``return` `-1;` `        ``// Finding index of first``        ``// value in this range``        ``while` `(s != e) {``            ``int` `m = (s + e) / 2;` `            ``// Update the value of``            ``// the minimum index``            ``if` `(Tree[2 * index] >= x) {``                ``e = m;``                ``index = 2 * index;``            ``}``            ``else` `{``                ``s = m + 1;``                ``index = 2 * index + 1;``            ``}``        ``}``        ``return` `s;``    ``}` `    ``// Find mid of the current range``    ``int` `m = (s + e) / 2;` `    ``// Left subtree``    ``int` `val = atleast_x(2 * index, s,``                        ``m, ql, qr, x);` `    ``if` `(val != -1)``        ``return` `val;` `    ``// If it does not lie in``    ``// left subtree``    ``return` `atleast_x(2 * index + 1, m + 1,``                     ``e, ql, qr, x);``}` `// Function for updating segment tree``void` `update(``int` `index, ``int` `s, ``int` `e,``            ``int` `new_val, ``int` `pos)``{``    ``// Update the value, we``    ``// reached leaf node``    ``if` `(s == e)``        ``Tree[index] = new_val;` `    ``else` `{` `        ``// Find the mid``        ``int` `m = (s + e) / 2;` `        ``if` `(pos <= m) {` `            ``// If pos lies in the``            ``// left subtree``            ``update(2 * index, s, m,``                   ``new_val, pos);``        ``}``        ``else` `{` `            ``// pos lies in the``            ``// right subtree``            ``update(2 * index + 1,``                   ``m + 1, e,``                   ``new_val, pos);``        ``}` `        ``// Update the maximum value``        ``// in the range``        ``Tree[index]``            ``= max(Tree[2 * index],``                  ``Tree[2 * index + 1]);``    ``}``}` `// Function to print the answer``// for the given queries``void` `printAnswer(``int``* arr, ``int` `n)``{``    ``// Build segment tree``    ``build(arr, 1, 0, n - 1);` `    ``// Find index of first value``    ``// atleast 2 in range [0, n-1]``    ``cout << atleast_x(1, 0, n - 1,``                      ``0, n - 1, 2)``         ``<< ``"\n"``;` `    ``// Update value at index 2 to 5``    ``arr = 5;``    ``update(1, 0, n - 1, 5, 2);` `    ``// Find index of first value``    ``// atleast 4 in range [0, n-1]``    ``cout << atleast_x(1, 0, n - 1,``                      ``0, n - 1, 4)``         ``<< ``"\n"``;` `    ``// Find index of first value``    ``// atleast 0 in range [0, n-1]``    ``cout << atleast_x(1, 0, n - 1,``                      ``0, n - 1, 0)``         ``<< ``"\n"``;``}` `// Driver Code``int` `main()``{``    ``int` `arr[] = { 1, 3, 2, 4, 6 };``    ``int` `N = ``sizeof``(arr) / ``sizeof``(arr);` `    ``// Function Call``    ``printAnswer(arr, N);` `    ``return` `0;``}`

## Java

 `// Java program to implement``// the above approach``import` `java.util.*;` `class` `GFG``{`` ` `static` `int` `maxN = ``100``;` `// Stores nodes value of the Tree``static` `int` `Tree[] = ``new` `int``[``4` `* maxN];` `// Function to build segment tree``static` `void` `build(``int` `arr[], ``int` `index,``           ``int` `s, ``int` `e)``{``    ``// Base Case``    ``if` `(s == e)``        ``Tree[index] = arr[s];` `    ``else``    ``{``      ` `        ``// Find the value of mid``        ``int` `m = (s + e) / ``2``;` `        ``// Update for left subtree``        ``build(arr, ``2` `* index, s, m);` `        ``// Update for right subtree``        ``build(arr, ``2` `* index + ``1``,``              ``m + ``1``, e);` `        ``// Update the value at the``        ``// current index``        ``Tree[index]``            ``= Math.max(Tree[``2` `* index],``                  ``Tree[``2` `* index + ``1``]);``    ``}``}` `// Function for finding the index``// of the first element at least x``static` `int` `atleast_x(``int` `index, ``int` `s, ``int` `e,``              ``int` `ql, ``int` `qr, ``int` `x)``{``    ``// If current range does``    ``// not lie in query range``    ``if` `(ql > e || qr < s)``        ``return` `-``1``;` `    ``// If current range is inside``    ``// of query range``    ``if` `(s <= ql && e <= qr) {` `        ``// Maximum value in this``        ``// range is less than x``        ``if` `(Tree[index] < x)``            ``return` `-``1``;` `        ``// Finding index of first``        ``// value in this range``        ``while` `(s != e) {``            ``int` `m = (s + e) / ``2``;` `            ``// Update the value of``            ``// the minimum index``            ``if` `(Tree[``2` `* index] >= x) {``                ``e = m;``                ``index = ``2` `* index;``            ``}``            ``else` `{``                ``s = m + ``1``;``                ``index = ``2` `* index + ``1``;``            ``}``        ``}``        ``return` `s;``    ``}` `    ``// Find mid of the current range``    ``int` `m = (s + e) / ``2``;` `    ``// Left subtree``    ``int` `val = atleast_x(``2` `* index, s,``                        ``m, ql, qr, x);``    ``if` `(val != -``1``)``        ``return` `val;` `    ``// If it does not lie in``    ``// left subtree``    ``return` `atleast_x(``2` `* index + ``1``, m + ``1``,``                     ``e, ql, qr, x);``}` `// Function for updating segment tree``static` `void` `update(``int` `index, ``int` `s, ``int` `e,``            ``int` `new_val, ``int` `pos)``{``  ` `    ``// Update the value, we``    ``// reached leaf node``    ``if` `(s == e)``        ``Tree[index] = new_val;``    ``else``    ``{` `        ``// Find the mid``        ``int` `m = (s + e) / ``2``;` `        ``if` `(pos <= m)``        ``{` `            ``// If pos lies in the``            ``// left subtree``            ``update(``2` `* index, s, m,``                   ``new_val, pos);``        ``}``        ``else``        ``{` `            ``// pos lies in the``            ``// right subtree``            ``update(``2` `* index + ``1``,``                   ``m + ``1``, e,``                   ``new_val, pos);``        ``}` `        ``// Update the maximum value``        ``// in the range``        ``Tree[index]``            ``= Math.max(Tree[``2` `* index],``                  ``Tree[``2` `* index + ``1``]);``    ``}``}` `// Function to print the answer``// for the given queries``static` `void` `printAnswer(``int``[] arr, ``int` `n)``{``  ` `    ``// Build segment tree``    ``build(arr, ``1``, ``0``, n - ``1``);` `    ``// Find index of first value``    ``// atleast 2 in range [0, n-1]``    ``System.out.println(atleast_x(``1``, ``0``, n - ``1``,``                      ``0``, n - ``1``, ``2``));` `    ``// Update value at index 2 to 5``    ``arr[``2``] = ``5``;``    ``update(``1``, ``0``, n - ``1``, ``5``, ``2``);` `    ``// Find index of first value``    ``// atleast 4 in range [0, n-1]``    ``System.out.println(atleast_x(``1``, ``0``, n - ``1``,``                      ``0``, n - ``1``, ``4``));` `    ``// Find index of first value``    ``// atleast 0 in range [0, n-1]``    ``System.out.println(atleast_x(``1``, ``0``, n - ``1``,``                      ``0``, n - ``1``, ``0``));``}``   ` `// Driver code``public` `static` `void` `main(String[] args)``{``    ``int` `arr[] = { ``1``, ``3``, ``2``, ``4``, ``6` `};``    ``int` `N = arr.length;` `    ``// Function Call``    ``printAnswer(arr, N);``}``}` `// This code is contributed by susmitakundugoaldanga.`

## Python3

 `# Python 3 program for the above approach``maxN ``=` `100` `# Stores nodes value of the Tree``Tree ``=` `[``0` `for` `i ``in` `range``(``4` `*` `maxN)]` `# Function to build segment tree``def` `build(arr, index, s, e):``  ` `    ``# Base Case``    ``global` `Tree``    ``global` `max``    ``if` `(s ``=``=` `e):``        ``Tree[index] ``=` `arr[s]``    ``else``:``      ` `        ``# Find the value of mid``        ``m ``=` `(s ``+` `e) ``/``/` `2` `        ``# Update for left subtree``        ``build(arr, ``2` `*` `index, s, m)` `        ``# Update for right subtree``        ``build(arr, ``2` `*` `index ``+` `1``, m ``+` `1``, e)` `        ``# Update the value at the``        ``# current index``        ``Tree[index] ``=` `max``(Tree[``2` `*` `index],``                          ``Tree[``2` `*` `index ``+` `1``])` `# Function for finding the index``# of the first element at least x``def` `atleast_x(index, s,  e,  ql, qr, x):``    ``global` `Tree``    ``global` `max``    ` `    ``# If current range does``    ``# not lie in query range``    ``if` `(ql > e ``or` `qr < s):``        ``return` `-``1` `    ``# If current range is inside``    ``# of query range``    ``if` `(s <``=` `ql ``and` `e <``=` `qr):``      ` `        ``# Maximum value in this``        ``# range is less than x``        ``if` `(Tree[index] < x):``            ``return` `-``1``;` `        ``# Finding index of first``        ``# value in this range``        ``while` `(s !``=` `e):``            ``m ``=` `(s ``+` `e) ``/``/` `2` `            ``# Update the value of``            ``# the minimum index``            ``if` `(Tree[``2` `*` `index] >``=` `x):``                ``e ``=` `m``                ``index ``=` `2` `*` `index``            ``else``:``                ``s ``=` `m ``+` `1``                ``index ``=` `2` `*` `index ``+` `1``        ``return` `s` `    ``# Find mid of the current range``    ``m ``=` `(s ``+` `e) ``/``/` `2` `    ``# Left subtree``    ``val ``=` `atleast_x(``2` `*` `index, s, m, ql, qr, x)``    ``if` `(val !``=` `-``1``):``        ``return` `val` `    ``# If it does not lie in``    ``# left subtree``    ``return` `atleast_x(``2` `*` `index ``+` `1``, m ``+` `1``,e, ql, qr, x)` `# Function for updating segment tree``def` `update(index, s, e, new_val, pos):``    ``global` `Tree``    ``global` `max``    ` `    ``# Update the value, we``    ``# reached leaf node``    ``if` `(s ``=``=` `e):``        ``Tree[index] ``=` `new_val``    ``else``:` `        ``# Find the mid``        ``m ``=` `(s ``+` `e) ``/``/` `2` `        ``if` `(pos <``=` `m):``            ``# If pos lies in the``            ``# left subtree``            ``update(``2` `*` `index, s, m,new_val, pos)``        ``else``:``            ``# pos lies in the``            ``# right subtree``            ``update(``2` `*` `index ``+` `1``, m ``+` `1``, e, new_val, pos)` `        ``# Update the maximum value``        ``# in the range``        ``Tree[index] ``=` `max``(Tree[``2` `*` `index], Tree[``2` `*` `index ``+` `1``])` `# Function to print the answer``# for the given queries``def` `printAnswer(arr, n):``    ``global` `Tree``    ``global` `max``    ` `    ``# Build segment tree``    ``build(arr, ``1``, ``0``, n ``-` `1``)` `    ``# Find index of first value``    ``# atleast 2 in range [0, n-1]``    ``print``(atleast_x(``1``, ``0``, n ``-` `1``, ``0``, n ``-` `1``, ``2``))` `    ``# Update value at index 2 to 5``    ``arr[``2``] ``=` `5``    ``update(``1``, ``0``, n ``-` `1``, ``5``, ``2``)` `    ``# Find index of first value``    ``# atleast 4 in range [0, n-1]``    ``print``(atleast_x(``1``, ``0``, n ``-` `1``, ``0``, n ``-` `1``, ``4``))` `    ``# Find index of first value``    ``# atleast 0 in range [0, n-1]``    ``print``(atleast_x(``1``, ``0``, n ``-` `1``, ``0``, n ``-` `1``, ``0``))` `# Driver Code``if` `__name__ ``=``=` `'__main__'``:``    ``arr ``=`  `[``1``, ``3``, ``2``, ``4``, ``6``]``    ``N ``=`  `len``(arr)``    ` `    ``# Function Call``    ``printAnswer(arr, N)` `    ``# This code is contributed by bgangwar59.`

## C#

 `// C# program to implement``// the above approach``using` `System;``class` `GFG``{``  ` `static` `int` `maxN = 100;` `// Stores nodes value of the Tree``static` `int``[] Tree = ``new` `int``[4 * maxN];` `// Function to build segment tree``static` `void` `build(``int``[] arr, ``int` `index,``           ``int` `s, ``int` `e)``{``    ``// Base Case``    ``if` `(s == e)``        ``Tree[index] = arr[s];` `    ``else``    ``{``      ` `        ``// Find the value of mid``        ``int` `m = (s + e) / 2;` `        ``// Update for left subtree``        ``build(arr, 2 * index, s, m);` `        ``// Update for right subtree``        ``build(arr, 2 * index + 1,``              ``m + 1, e);` `        ``// Update the value at the``        ``// current index``        ``Tree[index]``            ``= Math.Max(Tree[2 * index],``                  ``Tree[2 * index + 1]);``    ``}``}` `// Function for finding the index``// of the first element at least x``static` `int` `atleast_x(``int` `index, ``int` `s, ``int` `e,``              ``int` `ql, ``int` `qr, ``int` `x)``{``    ``// If current range does``    ``// not lie in query range``    ``if` `(ql > e || qr < s)``        ``return` `-1;` `    ``// If current range is inside``    ``// of query range``    ``if` `(s <= ql && e <= qr) {` `        ``// Maximum value in this``        ``// range is less than x``        ``if` `(Tree[index] < x)``            ``return` `-1;``    ` `        ``// Finding index of first``        ``// value in this range``        ``while` `(s != e) {``            ``int` `m = (s + e) / 2;` `            ``// Update the value of``            ``// the minimum index``            ``if` `(Tree[2 * index] >= x) {``                ``e = m;``                ``index = 2 * index;``            ``}``            ``else` `{``                ``s = m + 1;``                ``index = 2 * index + 1;``            ``}``        ``}``        ``return` `s;``    ``}` `    ``// Find mid of the current range``    ``int` `mm = (s + e) / 2;` `    ``// Left subtree``    ``int` `val = atleast_x(2 * index, s,``                        ``mm, ql, qr, x);``    ``if` `(val != -1)``        ``return` `val;` `    ``// If it does not lie in``    ``// left subtree``    ``return` `atleast_x(2 * index + 1, mm + 1,``                     ``e, ql, qr, x);``}` `// Function for updating segment tree``static` `void` `update(``int` `index, ``int` `s, ``int` `e,``            ``int` `new_val, ``int` `pos)``{``  ` `    ``// Update the value, we``    ``// reached leaf node``    ``if` `(s == e)``        ``Tree[index] = new_val;``    ``else``    ``{` `        ``// Find the mid``        ``int` `m = (s + e) / 2;` `        ``if` `(pos <= m)``        ``{` `            ``// If pos lies in the``            ``// left subtree``            ``update(2 * index, s, m,``                   ``new_val, pos);``        ``}``        ``else``        ``{` `            ``// pos lies in the``            ``// right subtree``            ``update(2 * index + 1,``                   ``m + 1, e,``                   ``new_val, pos);``        ``}` `        ``// Update the maximum value``        ``// in the range``        ``Tree[index]``            ``= Math.Max(Tree[2 * index],``                  ``Tree[2 * index + 1]);``    ``}``}` `// Function to print the answer``// for the given queries``static` `void` `printAnswer(``int``[] arr, ``int` `n)``{``  ` `    ``// Build segment tree``    ``build(arr, 1, 0, n - 1);` `    ``// Find index of first value``    ``// atleast 2 in range [0, n-1]``    ``Console.WriteLine(atleast_x(1, 0, n - 1,``                      ``0, n - 1, 2));` `    ``// Update value at index 2 to 5``    ``arr = 5;``    ``update(1, 0, n - 1, 5, 2);` `    ``// Find index of first value``    ``// atleast 4 in range [0, n-1]``    ``Console.WriteLine(atleast_x(1, 0, n - 1,``                      ``0, n - 1, 4));` `    ``// Find index of first value``    ``// atleast 0 in range [0, n-1]``    ``Console.WriteLine(atleast_x(1, 0, n - 1,``                      ``0, n - 1, 0));``}` `// Driver code``static` `void` `Main()``{``    ``int``[] arr = { 1, 3, 2, 4, 6 };``    ``int` `N = arr.Length;` `    ``// Function Call``    ``printAnswer(arr, N);` `}``}` `// This code is contributed by sanjoy_62`
Output:
```1
2
0```

Time Complexity: O(Q*log N)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live and Geeks Classes Live USA

My Personal Notes arrow_drop_up