问题分析

本问题的核心是在一维数轴上寻找一个长度不超过 的闭区间 ,使得该区间内覆盖的离散点(鸡窝)数量最大化。

  1. 概率本质:由于小鸡等概率出现在 个鸡窝中,成功“关鸡”的概率 ,其中 是落在区间 内的鸡窝数量。由于 是常数,最大化概率等价于最大化
  2. 区间边界确定性:对于任意一个包含 个点的最优区间 ,我们总可以通过平移该区间,使得区间的左端点 与该区间内最左侧的鸡窝坐标 重合,且不减少区间内点的数量。因此,搜索空间可以缩减为:以每个鸡窝坐标 作为左端点,寻找最大的下标 使得
  3. 数据规模
    • :要求算法复杂度至少达到
    • 坐标 及距离 达到 :必须考虑坐标的离散性,不能建立基于坐标值的数组,且计算差值时需注意数值范围。

算法:滑动窗口 (Sliding Window)

针对该模型,排序结合双指针(滑动窗口) 是最优的算法策略。

虽然可以通过对每个点进行二分查找(Binary Search)来确定右边界,从而实现 的复杂度。但滑动窗口利用了坐标的单调性,可以将搜索过程优化至线性 。结合预处理的排序,整体性能达到最优。

  • 预处理:首先对原始坐标数组 进行升序排序。排序后,若 ,则必有
  • 窗口定义:维护一个左指针 left 和右指针 right,代表当前考虑的候选区间范围。
  • 单调性维护
    • 随着 right 指针向右移动,区间长度 单调递增。
    • 当当前区间长度超过 时,必须向右移动 left 指针以收缩区间,直到重新满足
  • 全局最优解:在 right 遍历过程中,记录窗口内元素个数 right - left + 1 的历史最大值。

复杂度分析

1. 时间复杂度

  • 排序阶段:使用快速排序或归并排序,复杂度为
  • 滑动窗口阶段leftright 指针各遍历数组一次,复杂度为
  • 总复杂度

2. 空间复杂度

  • 辅助空间:除了存储输入坐标的数组外,仅需常数级别的额外变量。
  • 总复杂度 (取决于排序实现及输入存储)。

代码实现

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, k;
    cin >> n >> k;
    vector<int> x(n);
    for (int i = 0; i < n; i++)
        cin >> x[i];

    sort(x.begin(), x.end());

    int l = 0;
    int r = 0;
    int most = 0;
    while (r < n) {
        while (l <= r && x[r] - x[l] > k) {
            l++;
        }

        most = max(most, r - l + 1);
        r++;
    }

    double p = 1.0 * most / n;
    cout << fixed << setprecision(8) << p << endl;
}