def lower_bound(arr, l, r, x):
"""在数组 arr 的区间 [l, r) 中找到第一个大于等于 x 的元素的索引"""
while l < r:
mid = (l + r) // 2
if arr[mid] < x:
l = mid + 1
else:
r = mid
return l
def upper_bound(arr, l, r, x):
"""在数组 a 的区间 [l, r) 中找到第一个大于 x 的元素的索引"""
while l < r:
mid = (l + r) // 2
if arr[mid] <= x:
l = mid + 1
else:
r = mid
return l
def find_y(arr, op, l, r, x):
"""根据给出的option找到对应的y值"""
# 最小的 y 使得 x≤y 的指针为 lower_bound 。
if op == 1:
idx = lower_bound(arr, l, r, x)
return arr[idx] if idx < r and arr[idx] >= x else -1
# 最小的 y 使得 x<y 的指针为 upper_bound 。
elif op == 2:
idx = upper_bound(arr, l, r, x)
return arr[idx] if idx < r else -1
# 最大的 y 使得 y<x 的指针为 lower_bound−1 。
elif op == 3:
idx = lower_bound(arr, l, r, x)
return arr[idx - 1] if idx > l else -1
# 最大的 y 使得 y≤x 的指针为 upper_bound−1 。
elif op == 4:
idx = upper_bound(arr, l, r, x)
return arr[idx - 1] if idx > l and arr[idx - 1] <= x else -1
for _ in range(0,m):
op, left, right, x = map(int, input().split())
y = find_y(a, op, left, right, x)
print(y)
lower_bound 和 upper_bound 函数是二分查找算法的两种变体,它们在有序数组中查找特定元素的索引。下面我将解释这两个函数中的 if 条件是如何工作的:
lower_bound 函数
lower_bound 函数用于找到第一个大于等于给定值 x 的元素的索引。
if arr[mid] < x::检查中间元素是否小于x。如果是,则说明第一个大于等于x的元素在mid右侧(因为数组是有序的),所以我们更新左边界l为mid + 1。else::如果中间元素不小于x,那么mid可能就是我们要找的元素,或者第一个大于等于x的元素在mid的左侧。因此,我们将右边界r更新为mid。
通过这种方式,我们不断缩小搜索范围,直到找到第一个大于等于 x 的元素。
upper_bound 函数
upper_bound 函数用于找到第一个大于给定值 x 的元素的索引。
if arr[mid] <= x::检查中间元素是否小于等于x。如果是,则说明第一个大于x的元素在mid右侧,所以我们更新左边界l为mid + 1。else::如果中间元素大于x,那么mid可能就是我们要找的元素,或者第一个大于x的元素在mid的左侧。因此,我们将右边界r更新为mid。
同样,我们通过这种方式不断缩小搜索范围,直到找到第一个大于 x 的元素。
总的来说,这两个函数的关键在于如何根据中间元素与目标值 x 的比较结果来调整搜索范围。lower_bound 在找到大于等于 x 的元素时停止,而 upper_bound 在找到大于 x 的元素时停止。这两个函数都返回左边界 l,在二分查找结束时,l 就是我们要找的元素的索引(如果存在的话)。
操作 1 (op == 1)
idx = lower_bound(arr, l, r, x): 使用lower_bound函数找到第一个大于等于x的元素的索引。return arr[idx] if idx < r and arr[idx] >= x else -1: 如果找到的索引idx在区间[l, r)内,并且对应的元素大于等于x,则返回该元素。否则,返回-1。
操作 2 (op == 2)
idx = upper_bound(arr, l, r, x): 使用upper_bound函数找到第一个大于x的元素的索引。return arr[idx] if idx < r else -1: 如果找到的索引idx在区间[l, r)内,则返回该元素。否则,返回-1。
操作 3 (op == 3)
idx = lower_bound(arr, l, r, x): 使用lower_bound函数找到第一个大于等于x的元素的索引。return arr[idx - 1] if idx > l else -1: 如果找到的索引idx大于l,则返回索引idx - 1对应的元素。这是因为我们要找的是小于x的最大元素。如果idx等于l,则说明没有找到小于x的元素,返回-1。
操作 4 (op == 4)
idx = upper_bound(arr, l, r, x): 使用upper_bound函数找到第一个大于x的元素的索引。return arr[idx - 1] if idx > l and arr[idx - 1] <= x else -1: 如果找到的索引idx大于l,并且索引idx - 1对应的元素小于等于x,则返回该元素。否则,返回-1。
在每种操作中,我们都在寻找特定的元素,并使用 lower_bound 或 upper_bound 函数来确定该元素的索引。根据操作的不同,我们可能返回找到的元素,或者返回 -1(如果没有找到符合条件的元素)。
n, m = map(int,input().split())
a = list(map(int, input().split()))
def lower_bound(l, r, x):
"""在数组 arr 的区间 [l, r) 中找到第一个大于等于 x 的元素的索引"""
while l < r:
mid = (l + r) // 2
if a[mid] < x:
l = mid + 1
else:
r = mid
return l
def upper_bound(l, r, x):
"""在数组 a 的区间 [l, r) 中找到第一个大于 x 的元素的索引"""
while l < r:
mid = (l + r) // 2
if a[mid] <= x:
l = mid + 1
else:
r = mid
return l
for _ in range(0,m):
op, left, right, x = map(int, input().split())
# 最小的 y 使得 x≤y 的指针为 lower_bound 。
if(op==1):
idx = lower_bound(left,right,x)
if(idx==right):
print(-1)
else:
print(a[idx])
# 最小的 y 使得 x<y 的指针为 upper_bound 。
elif(op==2):
idx = upper_bound(left,right,x)
if(idx==right):
print(-1)
else:
print(a[idx])
# 最大的 y 使得 y<x 的指针为 lower_bound−1 。
elif(op==3):
idx = lower_bound(left,right,x)
if(idx==left):
print(-1)
else:
print(a[idx-1])
# 最大的 y 使得 y≤x 的指针为 upper_bound−1 。
else:
idx = upper_bound(left,right,x)
if(idx==left):
print(-1)
else:
print(a[idx-1])

京公网安备 11010502036488号