📌  相关文章
📜  查找具有更新的至少X值的[L,R]范围内的最小索引

📅  最后修改于: 2021-05-14 07:38:01             🧑  作者: Mango

给定一个由N个整数组成的数组arr []和一个由{X,L,R}类型的Q个查询组成的数组Queries []来执行以下操作:

  • 如果X的值为1 ,则将X索引处的数组元素更新为L。
  • 否则,在[L,R]范围内找到最小索引j ,以使arr [j]≥X 。如果不存在这样的j ,则打印“ -1”

例子:

天真的方法:最简单的方法是遍历每个查询的数组。对于类型1的查询,将A [X]更新为L。对于类型2的查询,遍历范围[L,R]的数组arr [ ]并找到满足条件的最小索引j 。如果找不到这样的索引,则打印“ -1”
时间复杂度: O(N * Q)
辅助空间: O(N)

高效的方法:为了优化上述方法,其思想是使用段树以有效地执行查询。请按照以下步骤解决问题:

  • 构造一个分段树,其中每个节点将代表该节点范围内的最大值。例如,对于任何给定范围[i,j] ,其对应的节点将包含该范围内的最大值。
  • 初始化一个变量,例如ans
  • 现在,对于类型2的查询,如果当前范围不在范围[L,R]内,则遍历其左子树。
  • 现在,在左子树中,如果最大值超过X并且当前范围位于范围[L,R]内,则转到该范围的中点,并检查其值是否大于X。如果发现是真的,请访问其左侧。否则,请访问其右侧。
  • 将变量ans更新为给定范围之间的最小索引(如果存在)。
  • 继续上述步骤,直到范围的左侧等于右侧。
  • 完成上述步骤后,输出ans的值作为结果。

下面是上述方法的实现:

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[2] = 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[0]);
 
    // 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[2] = 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


输出:
1
2
0

时间复杂度: O(Q * log N)
辅助空间: O(N)