欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > “二分查找 + (必要时)前缀和” -- 处理 ’有序数组‘ 的区间问题汇总

“二分查找 + (必要时)前缀和” -- 处理 ’有序数组‘ 的区间问题汇总

2025/4/4 8:34:32 来源:https://blog.csdn.net/2302_77889694/article/details/146987746  浏览:    关键词:“二分查找 + (必要时)前缀和” -- 处理 ’有序数组‘ 的区间问题汇总

例题1:
P3184 [USACO16DEC] Counting Haybales S - 洛谷

import sys, bisect# def satisfied(hay):
#     return True if hay in hays else Falsedata = sys.stdin.read().split()
data = iter(data)ans = []
N = int(next(data))
Q = int(next(data))hays = [int(next(data)) for _ in range(N)]
hays.sort() # 2 3 5 7 这样看区间比较直观for _ in range(Q):start = int(next(data))end = int(next(data))# .index() 太慢 -- 线性查找,不适合大数据  --> 建议bisect用于查找第一个target的位置# interval = hays.index(end) - hays.index(start) + 1 # index从0开始,需补1s_index = bisect.bisect_left(hays, start)e_index = bisect.bisect_right(hays, end)interval = e_index - s_index # # index从0开始,需补1ans.append(interval)sys.stdout.write("\n".join(map(str, ans)))

题目1:区间和查询(Range Sum Query)

题目描述
给定一个已排序的非负整数数组(长度 n),以及 Q 个查询。每个查询给出两个整数 L 和 R(表示数值),要求输出数组中所有落在 [L,R] 内的数的和;如果没有则输出 0。

import sys
import bisect
from itertools import accumulatedef range_sum_query():data = sys.stdin.read().split()it = iter(data)n = int(next(it))q = int(next(it))# 读取数组(题目保证数组已排序,否则需要 sort)arr = [int(next(it)) for _ in range(n)]# 构造前缀和:prefix[i] 表示前 i 个元素的和(prefix[0]=0)prefix = [0] + list(accumulate(arr))out_lines = []for _ in range(q):L = int(next(it))R = int(next(it))# 左边界:第一个不小于 L 的位置left = bisect.bisect_left(arr, L)# 右边界:第一个大于 R 的位置right = bisect.bisect_right(arr, R)sum_val = prefix[right] - prefix[left]out_lines.append(str(sum_val))sys.stdout.write("\n".join(out_lines))if __name__ == '__main__':range_sum_query()

题目2:大于某值的元素计数

题目描述
给定一个升序排列的数组和 Q个查询。每个查询给定一个整数 X,要求输出数组中大于 X 的元素个数

 

import sys, bisectdef count_greater():data = sys.stdin.read().split()it = iter(data)n = int(next(it))q = int(next(it))arr = [int(next(it)) for _ in range(n)]# 确保数组升序arr.sort()out_lines = []for _ in range(q):X = int(next(it))pos = bisect.bisect_right(arr, X)count = n - posout_lines.append(str(count))sys.stdout.write("\n".join(out_lines))if __name__ == '__main__':count_greater()

题目3:指定区间内的平均值查询

题目描述
给定一个排序好的数组和 Q 个查询,每个查询给出两个整数 L 和 R,要求计算数组中落在 [L,R] 内所有数的平均值;如果该区间内没有数字,则输出 -1

import sys, bisect
from itertools import accumulatedef interval_average_query():data = sys.stdin.read().split()it = iter(data)n = int(next(it))q = int(next(it))arr = [int(next(it)) for _ in range(n)]# 确保数组升序arr.sort()prefix = [0] + list(accumulate(arr))out_lines = []for _ in range(q):L = int(next(it))R = int(next(it))left = bisect.bisect_left(arr, L)right = bisect.bisect_right(arr, R)count = right - leftif count == 0:out_lines.append("-1")else:sum_val = prefix[right] - prefix[left]avg = sum_val / countout_lines.append(str(avg))sys.stdout.write("\n".join(out_lines))if __name__ == '__main__':interval_average_query()

题目4:“近似”区间计数问题

题目描述
给定一个升序排列的数组和 Q 个查询。每个查询给定两个整数 XX和 K,要求统计数组中所有与 X 的差值不超过 K 的元素个数,即统计区间 [X−K,X+K] 内的元素个数

import sys, bisectdef approximate_interval_count():data = sys.stdin.read().split()it = iter(data)n = int(next(it))q = int(next(it))arr = [int(next(it)) for _ in range(n)]arr.sort()out_lines = []for _ in range(q):X = int(next(it))K = int(next(it))L = X - KR = X + Kleft = bisect.bisect_left(arr, L)right = bisect.bisect_right(arr, R)count = right - leftout_lines.append(str(count))sys.stdout.write("\n".join(out_lines))if __name__ == '__main__':approximate_interval_count()

题目5:区间频率统计

题目描述
给定一个升序排列的数组和 Q 个查询,每个查询给定一个目标值 X,要求输出 X 在数组中出现的次数

import sys, bisectdef frequency_count():data = sys.stdin.read().split()it = iter(data)n = int(next(it))q = int(next(it))arr = [int(next(it)) for _ in range(n)]arr.sort()out_lines = []for _ in range(q):X = int(next(it))left = bisect.bisect_left(arr, X)right = bisect.bisect_right(arr, X)count = right - leftout_lines.append(str(count))sys.stdout.write("\n".join(out_lines))if __name__ == '__main__':frequency_count()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词