本题是2021-12-1的延伸拓展,第一题如果没看过可以看我上一篇的题解:CCF CSP 2021-12-1 题解及满分代码(C++11)
问题描述
题目背景
上一题“序列查询”中说道:
A = [ A 0 , A 1 , A 2 , ⋯ , A n ] A=[A0,A1,A2,⋯,An] A=[A0,A1,A2,⋯,An] 是一个由 n+1 个 [0,N) 范围内整数组成的序列,满足 0 = A 0 < A 1 < A 2 < ⋯ < A n < N 0=A0<A1<A2<⋯<An<N 0=A0<A1<A2<⋯<An<N。基于序列 A,对于 [0,N) 范围内任意的整数 x,查询 f(x) 定义为:序列 A 中小于等于 x 的整数里最大的数的下标。
对于给定的序列 A 和整数 x,查询 f(x) 是一个很经典的问题,可以使用二分搜索在 O(logn) 的时间复杂度内轻松解决。但在 IT 部门讨论如何实现这一功能时,小 P 同学提出了些新的想法。
题目描述
小 P 同学认为,如果事先知道了序列 A 中整数的分布情况,就能直接估计出其中小于等于 x 的最大整数的大致位置。接着从这一估计位置开始线性查找,锁定 f(x)。如果估计得足够准确,线性查找的时间开销可能比二分查找算法更小。
比如说,如果 A1,A2,⋯,An 均匀分布在 (0,N) 的区间,那么就可以估算出: f ( x ) ≈ ( n + 1 ) ⋅ x N f(x)≈(n+1)⋅xN f(x)≈(n+1)⋅xN
为了方便计算,小 P 首先定义了比例系数 r = ⌊ N n + 1 ⌋ r=⌊\frac{N}{n+1}⌋ r=<