题解 P7339 【『MdOI R4』Kotori】
C.kotori
Subtask 1
由于只有一个人,所以——士道一定是燃王!
于是只要输出
Subtask 2
因为是两个人,所以只有一场比赛。
根据规则,如果
Subtask 3
由于人数很少,因此我们可以直接考虑爆搜。
对于每场比赛,如果参赛双方都能获胜,则以双方获胜的情况分别搜一次;否则的话,只搜一次。
最坏情况复杂度
Subtask 4
由于
我们可以直接考虑模拟,求出每场比赛的胜者。
这里我们可以采用递归的方式,每次折半,然后找出两个半场的胜者,然后令他们两 PK。
注意如果比赛存在平票情况,那胜者可以任选;但如果此时有
复杂度为直接递归的复杂度
Subtask 5
回顾 Subtask 3,我们发现爆搜冗余的状态非常多。对于同一个人获胜,却可能存在着
受到 Subtask 4 的启发,我们可以考虑递归。
我们求出每一个子区间的所有可能的胜者,并将其以某种方式存起来,然后考虑这个区间的胜者。
对于每个左子区间可能的胜者,如果它要成为最终的胜者,那我们需要在右子区间寻找一个它可以击败(相差小于等于
我们枚举右子区间,逐个判断对应的选手能否被左子区间的这个选手击败,如果存在能击败的数则代表左子区间这个数可行,否则不可行。
依次合并即可。
Subtask 6~7
上一个 subtask 的做法已经接近正解了,我们只需要考虑如何优化。
其实非常简单,既然要在右子区间击败一个选手,那我们肯定是挑最菜的来击败啦~
于是就考虑如何维护这个最菜(粉丝人数最少)的选手。
如果使用一个堆的话,我们可以以
但我们回忆起一个经典的分治模型:归并排序,发现其实我们可以直接按照归并排序的方式来进行合并。
每次删除最小的不满足条件的,然后对剩余的进行归并,可以得到复杂度
事实上,由于区间的最大个数恒定,我们直接枚举区间内的值来找最小,复杂度同样为
当然,这里也可以使用一些可合并的数据结构,比如可并堆等,也可以以相同的复杂度通过。
方法很多,可以自行选择。
综合来说,这是一道比较水的题,放在 C 算是很送分了。
不过其实,这题很容易陷入的一个误区是直接考虑贪心。可惜大部分的贪心都是能够 hack 的,至少在赛前没有那位出题人拥有一个正确的贪心。
本题的主要考察点是分治思想,没有涉及到毒瘤的算法和长篇的代码。为良心的出题人点赞!
附一张琴里世萌冠军(萌王)的海报: