P7078 贪吃蛇
P7078 [CSP-S 2020] 贪吃蛇
性质一:
首先有一个性质是:
一个蛇如果吃了过后不是最弱的就一定会吃,证明:
假设有:
假设 \(e\) 吃了 \(a\) 不是最弱的,那么一定有:
\(b\le e-a\)
假设下一轮 \(d\) 又吃了 \(b\) :
那么 \(d\) 会变成:
由于后者编号更大,所以一定不是最弱的:
继续往后推:\(c\) 吃了 \(d\) ,则 \(c\) 变成
这是因为 \(c-d\le0\) ,\(b\le e-a\) 。
继续往后推都有 \(e-a\) 不是最弱的,所以 \(e-a\) 不会被吃掉。
性质二:
如果蛇 \(x\) 吃了过后变成最小的,抉择会是什么?
假设:
由于 \(f\) 吃了 \(a\) 后变成最小的了,那么:
假设 \(e\) 吃了 \(f\) ,那么就会变成:
因为 \(e-f\le 0\) ,\(a\le b\) 。
但此时 \(e\) 不一定是最弱的。因为 \(e\) 的编号比 \(b\) 大。
如果 \(e\) 不是最小的,那么 \(e\) 就会吃掉 \(f\) ,所以 \(f\) 就不能吃 \(a\) 。
而如果 \(e\) 是最小的,那 \(e\) 的决策就与 \(d\) 有关。
继续递归下去,直到某一只蛇吃了过后不是最弱。然后各个蛇决策就可以反推回去。
部分分:
大致是两部分,第一部分是当前蛇吃了不是最弱,那就一直吃。第二部分是当前蛇吃了就变成最弱的了,递归去反推决策。
直接用 \(set\) 维护就行了。
时间复杂度 \((Tn\log n)\)
正解:
要求 \(O(n)\) ,那没关系,回到刚刚我们推的式子。
第一部分:
根据我们刚刚推出来的式子:
-
一个蛇吃了过后不是最弱的就不会成为最弱的。
-
一个蛇吃了过后可能在某一轮会成为最强的,不能不管。
-
蛇吃了过后的值随轮次不增。
第三条容易证明,见性质一。
第二部分:
根据性质二中的式子:
-
一个蛇吃了过后变成最弱的后有可能会在后续的模拟中被吃掉,不能不管。
-
一个蛇吃了过后一定是最弱的,否则模拟终止,所以这条蛇会在下一轮模拟中被最强的蛇吃掉。
这两部分都可以用两个双端队列维护:
第一个队列中维护的是最开始的强弱排序,第二个维护的是蛇吃过后的新增的值的强弱排序。
由于两个序列都是有序的(第一部分第三条,第二部分第二条),选最小就取两个队列中最小的,选最大就取两个队列中最大的,还是一样维护就行了。

浙公网安备 33010602011771号