训练反应力
问题描述
小蓝正在努力成为一名航空员,这需要他锻炼出足够的反应力。
他来到一台用来训练反应力的机器前,训练的规则如下:小蓝可以选择在 N 个时间节点进行攻击。在某个时间节点 X 攻击机器后,机器将在 X + D 节点反击小蓝。此时,小蓝需要躲避,如果被机器击中,任务将失败。
小蓝无法在同一时间节点同时进行攻击和躲避。他想知道,在确保任务成功的前提下,自己最多能攻击机器多少次。
输入格式
第一行包含两个整数 N, D (1<=N<=1e5,1<=D<=1e9),分别表示时间节点的数量和机器反击的延迟。
第二行包含 N 个整数 Ai (A1 < A2 < ⋯ < AN ≤ 1e9),表示时间节点的具体值。
输出格式
输出一个整数,表示小蓝在确保任务成功的前提下,最多能攻击机器的次数。
样例输入
1 | 5 2 |
样例输出
1 | 3 |
思路
很明显的贪心,类似于活动选择问题:即当前时刻如果能攻击,则攻击。
需要一个严谨的贪心证明,这个证明与活动选择问题思路大致相同,但要分两种情况:
假设最终的最优攻击的时间点序列:x1, x2, ⋯, xn,其中不存在xi + D = xj, ∀i, j ≤ n。
反证法:假设x0并不在最优序列中(原始序列第一个值记作x0)
- x1 + D < x2,那么由于x0 < x1,有x0 + D < x2,此时可以将答案序列中的x1替换成x0,即此时x0在最优序列中。
- x1 + D > x2,此时还要分两种情况:
- x0 + D = x2,那此时说明选了x0后就不能再选x2,但由于x2 > x1,所以x0 + D = x2 > x1,所以此时可以删去最优序列中的x2,换成x0。因为x0不会和x1冲突,更不可能和x3, x4⋯冲突。此时x0在最优序列中。
- x0 + D ≠ x2,那此时说明选了x0和x2不会冲突,直接将x1替换为x0,序列中元素数量不变,此时x0在最优序列中
综上,作为原始序列的最小值x0,总是存在于最优序列中,于是可以遍历原始序列,依次加入当前状态下可以加入的最小值。
代码
1 | void solve() { |
复杂度
- 时间:O(n)
- 空间:O(n)
Comments
Comment plugin failed to load
Loading comment plugin