引入
首先我们以一道经典的海盗分金问题来做引入,这对这道题有很大启发。
我们有5 个海盗,他们要分 100 个金币,5 个海盗从一号开始一次提出自己的分金方案,然后投票表决。如果第一个海盗的方案得到了半数以上的人的同意,那么按照一号的方案分钱。否则一号会被扔到海里喂鲨鱼。然后再表决二号的方案,以此类推。假设所有海盗足够聪明,请问一号最多获得多少钱?
先说答案,如果没有做过这道题,你肯定会大吃一惊:979797.
具体海盗问题可自行了解下,会对理解这个题目有很大帮助。
这个题的思路就和贪吃蛇的思路有点类似了,我们现在再来理解 snakes 这道题会好很多。
我们现在考虑解题方法。
现在我们的蛇长度是 a1a_1a1 ,a2a_2a2 ,……,ana_nan 。吃一次会得到一条新的蛇an−a1a_n-a_1an −a1 ,长度为 因为蛇足够聪明,只要能吃,最长的蛇就一直吃,直到最长的蛇吃了最短的蛇后变成了最短的蛇。这符合贪心的策略。这个贪心思路很简单,一开始我就想到这里,开心打了代码。结果大样例和答案老是差 111。大概最后还剩半个小时的时候想到了这种情况:
1
3
3 4 5 6
以上是 70pts70pts70pts 做法,现在来考虑 100pts100pts100pts 做法。算法肯定没问题,主要是要把时间复杂度降到 O(n)O(n)O(n)。
我们其实可以联想到“蚯蚓”这道题,开两个队列来维护最大最小,吃完后留下的蛇的长度肯定是顺次单调递减的,很好证明,这里不再赘述。我们现在维护两个双端队列,由于有单调性,每个队列中蛇的长度单调递增,这样我们就省去了那个求最大最小值的 O(logn)O(logn)O(logn)。具体看代码。