Codeforces Global Round 11 A-F题解
很久以前,我在退役之后说过要在Codeforces上与你们再见。我回来了。
先写A-E的题解,F和G之后补。先写一部分可以防止咕咕咕。
F已经补上,G的题解非常妙,我将单独开一篇来介绍。
A. Avoiding Zero
重排一列数使得前缀和始终不为,可能无解。
题解:和为则显然无解,否则考虑分为正数和负数两部分,将和的绝对值大的那一部分放在前面,就不会出现前缀和为了。
B. Chess Cheater
你有自己场比赛的结果(赢或输),输的场不扣分,赢的场得一分,如果上一场也赢再得一分。你可以修改场比赛的结果,使得自己总分最大。
题解:显然只需要把输改为赢。那么修改完之后赢的场次就是,其中为本来就赢得的场次。
然后只需要最小化连赢的场的段数。可以通过把两段连赢之间的输改成赢来减少一段。那么只要按照连赢段之间的距离升序排序尽量消除就可以了。
C. The Hard Work of Paparazzi
有一个二维平面,从一点走到另一点所花的时间为。有个事件,第个在时刻在点发生。你时刻在,问最多参与多少事件。事件发生时刻严格递增。。
题解:比赛时居然没想到...老了老了。考虑朴素,表示参与号事件时之前最多参与了几个事件。普通的一次转移是的,但考虑如果时间差大于就肯定能到了,因此前面最多只有个事件是需要逐一判断的。复杂度优化为。
D. Unshuffling a Deck
你有一个长度为的排列,每次可以将其分割为若干段,段内顺序不变,所有段之间顺序反转。给出不多于次这样的操作将原排列排序。
题解:记录是排列中的第个。如果对,都有就排完了。否则找到某一个的。
设之后连续递增的一段为(即这个区间内),将排列分割为四段,用题中操作,操作完毕后,即与连在了一起,同时不会破坏任何已经连在一起的对。不断重复上述操作即可。
##E. Xum
黑板上初始有一个奇数,每次可以选黑板上两个数(可重复),再写出它们的和或异或和,重复若干步写出。限制比较宽松。
题解:我的做法是非标准的做法。考虑用线性基判定是否可以通过异或得到,先加和几次自身扩充一下线性基,之后每次随机从线性基中得到两个数取和加入,不久就会出解。对于的情况会比较苛刻,要先得到较大的倍数加入线性基中。
F. Boring Card Game
桌上有标号的张连续牌,Alice和Bob玩游戏轮流取张,Alice先取,每次取出位置连续的三张牌并将上下两堆牌合并。给出Alice最终拿到的所有牌的标号,复原一种可能的游戏过程,保证有解。
题解:
先考虑问题的弱化版:取消轮流取的限制,允许某人反复取三张牌,先判断这个条件下是否有解。
那么考虑一个贪心:从左到右扫描牌,逐一加入栈中,如果加入后栈顶出现三张属于同一个人的牌,就视为进行了一次取走操作,将这三张牌弹出。
如果贪心算法最终能将栈清空,显然就得到了一组合法解。现在来进一步证明如果弱化版问题有合法解那么栈一定被清空。
对取牌轮数用数学归纳法。
时显然成立。
假设时成立。时,对某种有解的情况,我们随意考虑它的某一个解,这个解的第一步取走的必定是标号连续的牌,设为。如果我们先打破贪心规则取走这三张牌,由数学归纳法,剩下的牌可以通过贪心构造一个解。
进一步转化,可以发现如果将之后的若干不依赖于三张牌被取走的前提就能取走的牌先于被取走,也是合法的。因此我们换一种打破规则的方式,改成在中的一些牌置于栈顶并可以取走时,如果并非这一组合就不取走,直到都出现在栈顶才取走它们(此时栈顶可能有张属于同一人的牌),也能在之后合乎贪心的过程给出一个解。
最后,由于是连续的,假设我们保留了本来可以取走的不取走,必定马上到来并将带走,此时栈顶留下,但是如果我们合乎规则操作,直接取走,栈顶就剩下,由于这些牌的归属者相同,对于之后的过程来说,除了标号和没有本质区别,因此原来能得出解此刻仍然可以得出解。的情况也是类似的。而此时是完全符合贪心规则的。因此也就证明完毕了。
因此原问题有解的必要条件是栈能够清空,也就是得出一种弱化版的方案,现在再来分析一下该方案中每一组牌之间的依赖关系。可以得知,如果我们让三张牌对应到包含这三张牌编号的最小区间,那么任何两个区间之间只有无交和包含两种关系,因此可以建立一个森林,树中祖先的区间包含所有后代的区间。对于这三张牌,显然只有其子树对应的三张牌组取完才可以取。不难发现,对一组三张牌,尽管其后代中可能存在归属者相同的牌组,但由贪心的性质其儿子对应的归属者都是与自己的不同的。
重新考虑轮流取的限制,我们对森林的操作就变成了:只有所有叶子都已经被取走的节点可以被取走,且必须的牌的点和的牌的点轮流取走。考虑是否存在这样一个取走的序列。
首先,最后一组取走的牌一定是森林中某棵树的根。因此,如果所有根都是的牌,就一定无解。那么下面只要说明森林里有一棵树的根属于,就一定能找到一组解。
要取的节点时,假设没有的节点作叶子,那么所有和某个儿子节点配对。但是节点至少有一个根,不满足条件,因此有叶子节点,随意取一个即可。
而要取的节点时,此时的节点多一个。分两种情况:的根只有一个和有多个。
如果有多个,假设没有叶子,就令每个点和某儿子点配对,而点少一个,必不可行。又由于根多于一个,取走一个并不影响“存在至少一个根”这一性质,因此随便取。
如果只有一个,那么再分类:
如果这个点有儿子,本来就不可取,直接利用结论随便取走一个叶子即可。
如果这个点没有儿子,且除了它以外没有别的树,它就是最后一个点,显然可以取走。如果没有儿子且还有别的树,一定是以为根,不考虑这个点后的讨论和相似,一定可以找到另一个叶子。