给定一个由N个整数组成的数组arr []和一个由{X,L,R}类型的Q个查询组成的数组Queries []来执行以下操作:
- 如果X的值为1 ,则将第X个索引处的数组元素更新为L。
- 否则,在[L,R]范围内找到最小索引j ,以使arr [j]≥X 。如果不存在这样的j ,则打印“ -1” 。
例子:
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.
天真的方法:最简单的方法是遍历每个查询的数组。对于类型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)