[贪心] P7078 [CSP-S2020] 贪吃蛇

posted on 2024-07-17 13:15:22 | under | source

先让所有蛇排个序,从小到大依次为 \(a_1\dots a_n\)

阅读完题面,显然,\(a_n\) 具有最高决定权,因为足够聪明,它一定会预演所有情况选择最优的,当然,以自己存活为基础。换言之,假如 \(a_n\)\(a_1\) 后不会死,一定吃;否则直接结束。

有一个结论:假如当前最大的蛇吃了最小的蛇之后,不是最小的那条,那么它一定吃。

原因:考虑吃完后最大的蛇,若还是 \(a_n\) 那没有影响 \(a_n\) 肯定吃 \(a_1\);否则,对于 \(a_{n-1}\),必然有 \(a_{n-1}-a_2\le a_{n}-a_1\),所以假如 \(a_{n-1}\) 选择吃,它就会比 \(a_n\) 小,从而死在 \(a_n\) 前面。由于 \(a_{n-1}\) 不会让自己死,所以 \(a_n\) 也不会死。

那么假如 \(a_n\) 变成了最小的那条蛇怎么办?需要考虑 \(a_{n-1}\) 会不会吃,这构成递归的形式!假如 \(a_{n-1}\) 出于某些原因不吃 \(a_n\),那么 \(a_n\) 一定决定去吃;否则 \(a_n\) 直接结束。

我们尝试将这个递归层画出来,那么递归条件是“变成最小的蛇”,终止条件就是“选择吃”(吃完非最小、或只剩两只),例如:\(a_n\) 考虑 \(a_{n-1}\)\(a_{n-1}\) 考虑 \(a_{n-2}\) \(\dots\),若最终 \(a_{n-p}\) 发现可以吃停止“考虑”,那么往上倒推:\(a_{n-p+1}\) 不想死于是不吃、\(a_{n-p+2}\) 发现即使变成最小依旧不会死于是吃、\(a_{n-p+3}\) 不吃、\(a_{n-p+4}\)\(\dots\) 总而言之,我们发现 \(a_{n}\) 到底吃不吃只和 \(p\) 的奇偶性有关!

更有趣的是,对于上面的情况,假如 \(a_n\) 不吃,直接结束;假如 \(a_n\) 吃,按照递归层,\(a_{n-1}\) 不会吃,依旧结束。无需考虑后续问题了。

于是用 set 维护这个过程,具体而言,分为两部分:最大的蛇一直吃最小的,一直不会变成新的最小的蛇;最大的蛇发现吃完变最小,于是模拟此后的局面直到终止,最后计算吃不吃然后结束。

于是喜提 \(O(n\log n)\) 做法!怎么去掉烦人的 \(\log\) 呢?根据一开始的讨论,容易发现,新产生的蛇(最大吃完最小变成的蛇)的实力是递减的。又因为一开始序列有序,所以拿两个单调队列存原序列和新序列的蛇即可。

细节有点恶心,一定要好好处理“相同实力,比较编号”这一步骤。

posted @ 2026-01-14 18:10  Zwi  阅读(0)  评论(0)    收藏  举报