P7078 [CSP-S2020] 贪吃蛇

[CSP-S2020] 贪吃蛇

题目描述

草原上有 \(n\) 条蛇,编号分别为 \(1, 2, \ldots, n\)。初始时每条蛇有一个体力值 \(a_i\),我们称编号为 \(x\) 的蛇实力比编号为 \(y\) 的蛇强当且仅当它们当前的体力值满足 \(a_x > a_y\),或者 \(a_x = a_y\)\(x > y\)

接下来这些蛇将进行决斗,决斗将持续若干轮,每一轮实力最强的蛇拥有选择权,可以选择吃或者不吃掉实力最弱的蛇:

  1. 如果选择吃,那么实力最强的蛇的体力值将减去实力最弱的蛇的体力值,实力最弱的蛇被吃掉,退出接下来的决斗。之后开始下一轮决斗。
  2. 如果选择不吃,决斗立刻结束。

每条蛇希望在自己不被吃的前提下在决斗中尽可能多吃别的蛇(显然,蛇不会选择吃自己)。

现在假设每条蛇都足够聪明,请你求出决斗结束后会剩几条蛇。

本题有多组数据,对于第一组数据,每条蛇体力会全部由输入给出,之后的每一组数据,会相对于上一组的数据,修改一部分蛇的体力作为新的输入。


思路

简化一下问题, 我们假设当前单调不降的序列为 \(a_1, a_2 , \dots, a_n\), 从队尾的 \(a_n\) 开始分情况考虑

  1. 如果 \(a_n\) 吃完 \(a_1\) 后还是最大的, 那么不吃白不吃, \(a_n\) 一定会吃掉 \(a_1\).

  2. 如果 \(a_n\) 吃完 \(a_1\) 后就不是最大的了, 但同时也不是最小的, 那么此时最强的蛇是 \(a_{n - 1}\), 最弱的蛇为 \(a_2\), 由于 \(a_n \ge a_{n - 1}, a_1 \le a_2\), 所以 \(a_{n - 1} - a_2 \le a_n - a_1\), 也就是 \(a_{n - 1}\) 在吃掉 \(a_2\) 后一定会排在 \(a_n\) 之前, 换句话说, \(a_{n - 1}\) 选择吃了 \(a_2\) 过后就一定会比 \(a_n\) 先死. 因为所有蛇都采用最优策略, 也就是尽可能保证自己不死, 所以 \(a_n\)​ 仍然是安全的.

  3. 最后一种情况, 也即 \(a_n\) 吃完 \(a_1\) 后变为最小的蛇. 从大局来说, 如果 \(a_n\) 吃完 \(a_1\) 后到最后不会死, 那么他一定选择吃, 否则选择不吃.

    我们类似递归的考虑一下这件事情.

    假设 \(a_n\) 吃了 \(a_1\) 后变为最小的, 接着 \(a_{n - 1}\) 吃了 \(a_n\) 后不为最小的, 那么 \(a_{n - 1}\) 一定会选择吃, 倒过来 \(a_n\) 在第一步做决策的时候就一定会选择不吃来保证自己不死.

    顺着上面的假设, 在 \(a_n\) 吃了 \(a_1\) 后变为最小的基础上再假设 \(a_{n - 1}\) 吃了后是最小的, 此时 \(a_{n - 2}\) 吃了后不为最小的, 那么 \(a_{n - 2}\) 一定会选择吃, 那么 \(a_{n - 1}\) 一定会选择不吃, \(a_n\) 一定会选择吃.

    \(\dots\)

不难发现这个递归的终止条件为「某一轮中最大的蛇在吃掉最小的蛇后不为最小的」或者「只剩下 \(2\) 条蛇」, 那么最后一条会选择吃, 倒数第二条会选择不吃, 倒数第三条会选择吃 \(\dots\)

这样, \(a_n\) 的决策就和终止蛇的奇偶性相关了.

使用 set 我们可以较为方便的维护当前的最小蛇和最大蛇, 正向模拟一遍, 直到有递归终止条件为止.

复杂度 \(\mathcal{O}(Tn \log n)\). 如果使用两个双端队列维护可以做到 \(\mathcal{O}(Tn)\).

posted @ 2025-05-21 21:09  Steven1013  阅读(34)  评论(0)    收藏  举报