#5. 数的范围

数的范围

给定一个按照升序排列的长度为 nn 的整数数组,以及 qq 个查询。

对于每个查询,返回一个元素 kk 的起始位置和终止位置(位置从 00 开始计数)。

如果数组中不存在该元素,则返回 -1 -1

输入格式

第一行包含整数 nnqq,表示数组长度和询问个数。

第二行包含 nn 个整数(均在 1100001 \sim 10000 范围内),表示完整数组。

接下来 qq 行,每行包含一个整数 kk,表示一个询问元素。

输出格式

qq 行,每行包含两个整数,表示所求元素的起始位置和终止位置。

如果数组中不存在该元素,则返回 -1 -1

数据范围

1n1000001 \le n \le 100000
1q100001 \le q \le 10000
1k100001 \le k \le 10000

输入样例:

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 压力等)。

下载测试数据(zip)

下面按 1..25 逐组说明每组主要在卡哪些常见错误做法(正确:两次二分找 lower_bound/upper_bound,注意 0-based,右端是 upper-1,不存在输出 -1 -1):

  1. 样例:基础正确性(存在/不存在混合)。
  2. n=1 命中+不命中:卡边界与输出 -1 -1
  3. 全相同(10 个 5):卡重复段边界(应输出 0 9),以及不存在时输出。
  4. 严格递增无重复:卡单点位置(l=r)、首尾元素、以及缺失值处理。
  5. 重复在开头和结尾:卡“左边界=0”“右边界=n-1”两种极端;也卡只找一次二分。
  6. 多段重复块:综合卡多块边界(每个值段长度不同),以及夹在中间的缺失值(5/11)。
  7. 重复查询同一个 k:卡程序“带状态”错误(上次结果污染下一次)。
  8. 包含 k=1 与 k=10000 的边界值:卡值域边界、以及末尾重复段右边界计算。
  9. n=1000 随机+q=50:综合正确性(一般 bug 会暴露)。
  10. n=100000:1..10000 每个重复 10 次:卡大规模 + 规律边界(比如 5000 的区间应是连续 10 个位置),也卡性能。
  11. n=100000 全是 10000:卡极端重复(应输出 0 99999),以及对不存在值返回 -1。
  12. n=100000 值域 1..50(超多重复):卡重复值密集时 lower/upper 的正确性与性能。
  13. n=100000 值域 1..10000 随机 + q=1000:综合强测(性能+正确性)。
  14. k 只出现在末尾段(右边界 off-by-one):如 [... 4,4,4,4,4] 查询 4;卡 upper-1 是否写对、是否越界。
  15. k 只出现在开头段(左边界 off-by-one):查询 7;卡 lower_bound 是否正确、是否漏掉开头。
  16. k 不存在且夹在相邻值中间:如只有 1/3/5,查 2/4/6;卡“找不到时不要输出插入位置”。
  17. 1..100 多段重复(每段长度 v%5+1)+ 查询每个值:卡大量不同段边界,容易暴露 “右边界少 1 / 多 1”。
  18. q=10000 压力但 n 很小:卡 I/O 与每次查询必须 O(log n),也卡循环输出格式(别漏行/多行)。
  19. n=100000:90000 个 1 + 10000 个随机(2..10000):卡极端偏斜分布(1 的区间很长),以及其他值可能不存在。
  20. n=99999 + q=9999 接近上限:强卡性能与实现稳定性(别 O(nq) 扫描)。
  21. 目标值只出现一次且在中间:卡单点段(l=r)计算。
  22. 只查最小/最大值(1 与 10000):卡边界值在数组中可能不存在时的处理。
  23. 超大三段块(1/2/3)长度不等:卡段边界计算是否精确(尤其第三段长度不同)。
  24. 只在最后一个位置出现一次[1]*99999 + [2] 查询 2/1;卡右边界=n-1 的单点情况。
  25. 只在第一个位置出现一次[2] + [3]*99999 查询 2/3;卡左边界=0 的单点情况。

后面你继续发题,我会同样:生成数据包 + 逐组说明每组卡什么常见错误。