P7078 贪吃蛇

P7078 [CSP-S 2020] 贪吃蛇

性质一:

首先有一个性质是:

一个蛇如果吃了过后不是最弱的就一定会吃,证明:

假设有:

\[a\le b\le c\le d\le e \]

假设 \(e\) 吃了 \(a\) 不是最弱的,那么一定有:

\(b\le e-a\)

假设下一轮 \(d\) 又吃了 \(b\) :

那么 \(d\) 会变成:

\[d-b\le e-a \]

由于后者编号更大,所以一定不是最弱的:

继续往后推:\(c\) 吃了 \(d\) ,则 \(c\) 变成

\[c-d+b\le e-a \]

这是因为 \(c-d\le0\) ,\(b\le e-a\) 。

继续往后推都有 \(e-a\) 不是最弱的,所以 \(e-a\) 不会被吃掉。

性质二:

如果蛇 \(x\) 吃了过后变成最小的,抉择会是什么?

假设:

\[a\le b\le c\le d\le e\le f \]

由于 \(f\) 吃了 \(a\) 后变成最小的了,那么:

\[f-a<a\le b\le c\le d\le e \]

假设 \(e\) 吃了 \(f\) ,那么就会变成:

\[e-f+a\le b \]

因为 \(e-f\le 0\) ,\(a\le b\) 。

但此时 \(e\) 不一定是最弱的。因为 \(e\) 的编号比 \(b\) 大。

如果 \(e\) 不是最小的,那么 \(e\) 就会吃掉 \(f\) ,所以 \(f\) 就不能吃 \(a\) 。

而如果 \(e\) 是最小的,那 \(e\) 的决策就与 \(d\) 有关。

继续递归下去,直到某一只蛇吃了过后不是最弱。然后各个蛇决策就可以反推回去。

部分分:

大致是两部分,第一部分是当前蛇吃了不是最弱,那就一直吃。第二部分是当前蛇吃了就变成最弱的了,递归去反推决策。

直接用 \(set\) 维护就行了。

时间复杂度 \((Tn\log n)\)

正解:

要求 \(O(n)\) ,那没关系,回到刚刚我们推的式子。

第一部分:

根据我们刚刚推出来的式子:

  • 一个蛇吃了过后不是最弱的就不会成为最弱的。

  • 一个蛇吃了过后可能在某一轮会成为最强的,不能不管。

  • 蛇吃了过后的值随轮次不增。

第三条容易证明,见性质一。

第二部分:

根据性质二中的式子:

  • 一个蛇吃了过后变成最弱的后有可能会在后续的模拟中被吃掉,不能不管。

  • 一个蛇吃了过后一定是最弱的,否则模拟终止,所以这条蛇会在下一轮模拟中被最强的蛇吃掉。

这两部分都可以用两个双端队列维护:

第一个队列中维护的是最开始的强弱排序,第二个维护的是蛇吃过后的新增的值的强弱排序。

由于两个序列都是有序的(第一部分第三条,第二部分第二条),选最小就取两个队列中最小的,选最大就取两个队列中最大的,还是一样维护就行了。

posted @ 2026-10-09 09:04  wlhao  阅读(13)  评论(0)    收藏  举报