求助:用Binary Search解决Codeforces饮品问题时结果偏差(非超时)
问题分析与修正
你的代码结果少1的核心原因是二分查找逻辑不严谨,具体问题如下:
错误点拆解
- 提前终止循环:当找到
prices[mid] == m时直接break,此时mid只是某个等于m的元素位置,而非最后一个小于等于m的元素索引。若数组存在多个等于m的元素,会漏掉后续符合条件的商店数量。 - 多余的mid更新:循环内手动执行
mid = (l+r)//2完全多余,每次循环开头会重新计算mid,这会干扰最终mid的取值逻辑。 - 循环结束后的判断逻辑错误:当循环因
l > r自然退出时,mid的取值是最后一次循环的中间值,已不符合当前l和r的范围,此时用prices[mid] <= m判断会出现偏差。
修正后的代码(两种实现方式)
方式1:找第一个大于m的元素位置(推荐)
利用二分查找找upper_bound(第一个大于目标值的元素索引),该索引即为符合条件的商店总数(因为数组已排序,前面所有元素都<=m):
n = int(input()) prices = list(map(int, input().split())) prices.sort() q = int(input()) for _ in range(q): m = int(input()) l, r = 0, n # 左闭右开区间 while l < r: mid = (l + r) // 2 if prices[mid] > m: r = mid else: l = mid + 1 print(l)
方式2:找最后一个<=m的元素索引
记录最后一个满足prices[mid] <= m的索引,最终结果为该索引+1(若不存在则为0):
n = int(input()) prices = list(map(int, input().split())) prices.sort() q = int(input()) for _ in range(q): m = int(input()) l, r = 0, n - 1 last_valid = -1 while l <= r: mid = (l + r) // 2 if prices[mid] <= m: last_valid = mid l = mid + 1 # 尝试向右寻找更靠后的符合条件元素 else: r = mid - 1 print(last_valid + 1 if last_valid != -1 else 0)
逻辑说明
- 两种方式都基于排序后的数组,保证二分查找的正确性。
- 方式1的左闭右开区间写法更简洁,避免了边界条件的复杂判断,适合大规模数据(符合题目n和q均为1e5的要求)。
内容的提问来源于stack exchange,提问作者NetherXp
相关产品推荐
相关产品推荐

