#LC875. 爱吃香蕉的珂珂
爱吃香蕉的珂珂
你好,同学。我是你的 OI 教练。今天我们要攻克的是一道非常经典、也是 NOI 竞赛中“二分答案”专题的必修题——爱吃香蕉的珂珂。
在信息学奥赛中,当我们遇到“求某个值的最小可能值,且该值具有单调性”的问题时,二分答案几乎是标准动作。请拿出草稿纸,随我一起拆解这道题。
一、 预备知识点
- 二分答案 (Binary Search on Answer):将求解问题转化为判定性问题。
- 单调性 (Monotonicity):吃香蕉的速度越快,所需的时间越短。
- 向上取整技巧:计算一堆香蕉需要多少小时时, 可以写成
(a + b - 1) / b。 - 时间复杂度分析:理解 的效率优势。
二、 题目描述 (NOI 风格)
题目名称:爱吃香蕉的珂珂 (koko)
输入文件:koko.in
输出文件:koko.out
【问题描述】 珂珂喜欢吃香蕉。这里有 堆香蕉,第 堆中有 根香蕉。警卫已经离开了,将在 小时后回来。 珂珂可以决定她吃香蕉的速度 (单位:根/小时)。每个小时,她将会选择一堆香蕉,从中吃掉 根。如果这堆香蕉少于 根,她将吃光这堆香蕉,并且这一小时内不会再吃更多的香蕉。 珂珂喜欢慢慢吃,但仍然希望能在警卫回来前吃完所有的香蕉。 请你编写一个程序,求出她能在 小时内吃完所有香蕉的最小整数速度 。
【输入格式】 第一行包含两个整数 和 ,分别表示香蕉堆数和警卫回来的时间。 第二行包含 个由空格隔开的正整数,表示每堆香蕉的数量 。
【输出格式】 输出一个整数,表示最小的吃香蕉速度 。
【样例 1 输入】
4 8
3 6 7 11
【样例 1 输出】
4
【样例 2 输入】
5 5
30 11 23 4 20
【样例 2 输出】
30
【样例 3 输入】
5 6
30 11 23 4 20
【样例 3 输出】
23
【数据范围限制】
三、 启发式引导:草稿纸上的推理过程
请在草稿纸上跟我一起画:
1. 寻找单调性
- 如果珂珂以 根/小时的速度能吃完,那么以 根/小时的速度一定也能吃完。
- 如果珂珂以 根/小时的速度吃不完,那么以 根/小时的速度一定更吃不完。
- 这种“可行性”随速度增加而从“不可行”变为“可行”的性质,就是单调性。
2. 确定二分的值域 [L, R]
- 左边界 L:最小速度是 。
- 右边界 R:最大速度其实不需要超过数组中的最大值(因为每小时只能吃一堆,速度再快也得花 小时)。
3. 判定函数 (Check)
假设珂珂当前的速度是 ,计算总耗时:
- 对于每一堆 ,所需时间是 。
- 累加所有堆的时间,如果总和 ,说明速度 合法。
四、 算法思路流程图 (C++ 14 伪代码逻辑)
graph TD
A(开始) --> B(读取n和h以及数组piles)
B --> C(设置L等于1, R等于数组中的最大值)
C --> D{L 小于 R}
D -- 否 --> E(输出最终答案L)
D -- 是 --> F(Mid 等于 L加R的一半)
F --> G(计算以速度Mid吃完所需的总时间Total)
G --> H{Total 是否小于等于 h}
H -- 是 --> I(速度够快, 尝试更小的速度: R等于Mid)
H -- 否 --> J(速度太慢, 必须加速: L等于Mid加1)
I --> D
J --> D
subgraph Check函数逻辑
K(遍历piles数组) --> L(当前堆耗时等于 -p加Mid减1- 除以 Mid)
L --> M(累加到Total)
M --> K
end
五、 复杂度分析与优化建议
1. 时间复杂度
- 二分次数:,由于 ,二分大约进行 次。
- 判定函数:每次判定需要遍历一次数组,复杂度 。
- 总复杂度:,其中 ,。总运算量约为 ,在 NOI 1秒时限内绰绰有余。
2. 空间复杂度
- 存储数组需要 空间。
3. 优化建议与易错点
- 数据范围:虽然 在
int范围内,但累加的总时间Total可能会超过 。在判定函数中建议使用long long存储时间总和,防止溢出。 - 向上取整:避免使用
double和ceil(),在竞赛中浮点数精度可能带来风险。使用(p + mid - 1) / mid是更稳健的整数技巧。
六、 总结:读题关键词
在面对 NOI 题目时,看到以下描述应立即联想到二分答案:
- “求最小的整数速度...”:典型的最优化问题。
- “每个小时只能吃一堆”:限定了判定的逻辑(贪心判定)。
- “速度越快时间越短”:隐含的单调性条件。
- 数据范围对比: 较小 (),但 和 很大 (),说明不能直接枚举时间或速度。
同学,思路清晰了吗?现在请在草稿纸上尝试写出 check 函数的具体实现。注意 long long 的使用!加油。