#5. 数的范围
数的范围
给定一个按照升序排列的长度为 的整数数组,以及 个查询。
对于每个查询,返回一个元素 的起始位置和终止位置(位置从 开始计数)。
如果数组中不存在该元素,则返回 -1 -1。
输入格式
第一行包含整数 和 ,表示数组长度和询问个数。
第二行包含 个整数(均在 范围内),表示完整数组。
接下来 行,每行包含一个整数 ,表示一个询问元素。
输出格式
共 行,每行包含两个整数,表示所求元素的起始位置和终止位置。
如果数组中不存在该元素,则返回 -1 -1。
数据范围
输入样例:
6 3
1 2 2 3 3 4
3
4
5
输出样例:
3 4
5 5
-1 -1
已按 OJ 可直接用的 1.in/1.out ... 25.in/25.out 生成 25 组“有序数组中查询某元素的起始/终止位置(0-based)”测试数据(覆盖:不存在、全相同、只出现一次、出现在两端、重复查询、q=10000 压力、n=100000 压力等)。
下面按 1..25 逐组说明每组主要在卡哪些常见错误做法(正确:两次二分找 lower_bound/upper_bound,注意 0-based,右端是 upper-1,不存在输出 -1 -1):
- 样例:基础正确性(存在/不存在混合)。
- n=1 命中+不命中:卡边界与输出
-1 -1。 - 全相同(10 个 5):卡重复段边界(应输出
0 9),以及不存在时输出。 - 严格递增无重复:卡单点位置(l=r)、首尾元素、以及缺失值处理。
- 重复在开头和结尾:卡“左边界=0”“右边界=n-1”两种极端;也卡只找一次二分。
- 多段重复块:综合卡多块边界(每个值段长度不同),以及夹在中间的缺失值(5/11)。
- 重复查询同一个 k:卡程序“带状态”错误(上次结果污染下一次)。
- 包含 k=1 与 k=10000 的边界值:卡值域边界、以及末尾重复段右边界计算。
- n=1000 随机+q=50:综合正确性(一般 bug 会暴露)。
- n=100000:1..10000 每个重复 10 次:卡大规模 + 规律边界(比如 5000 的区间应是连续 10 个位置),也卡性能。
- n=100000 全是 10000:卡极端重复(应输出
0 99999),以及对不存在值返回 -1。 - n=100000 值域 1..50(超多重复):卡重复值密集时 lower/upper 的正确性与性能。
- n=100000 值域 1..10000 随机 + q=1000:综合强测(性能+正确性)。
- k 只出现在末尾段(右边界 off-by-one):如
[... 4,4,4,4,4]查询 4;卡upper-1是否写对、是否越界。 - k 只出现在开头段(左边界 off-by-one):查询 7;卡 lower_bound 是否正确、是否漏掉开头。
- k 不存在且夹在相邻值中间:如只有 1/3/5,查 2/4/6;卡“找不到时不要输出插入位置”。
- 1..100 多段重复(每段长度 v%5+1)+ 查询每个值:卡大量不同段边界,容易暴露 “右边界少 1 / 多 1”。
- q=10000 压力但 n 很小:卡 I/O 与每次查询必须 O(log n),也卡循环输出格式(别漏行/多行)。
- n=100000:90000 个 1 + 10000 个随机(2..10000):卡极端偏斜分布(1 的区间很长),以及其他值可能不存在。
- n=99999 + q=9999 接近上限:强卡性能与实现稳定性(别 O(nq) 扫描)。
- 目标值只出现一次且在中间:卡单点段(l=r)计算。
- 只查最小/最大值(1 与 10000):卡边界值在数组中可能不存在时的处理。
- 超大三段块(1/2/3)长度不等:卡段边界计算是否精确(尤其第三段长度不同)。
- 只在最后一个位置出现一次:
[1]*99999 + [2]查询 2/1;卡右边界=n-1 的单点情况。 - 只在第一个位置出现一次:
[2] + [3]*99999查询 2/3;卡左边界=0 的单点情况。
后面你继续发题,我会同样:生成数据包 + 逐组说明每组卡什么常见错误。