IOI 2022 Day2 题解 & 锐评

· · 个人记录

IOI 2022 D2T1 Circuit

题目大意:

给定一个 N 个非叶结点,M 个叶结点的值,叶结点有初值 01,某个非叶结点如果有 x 个儿子,则需要设置一个参数 y\in [1,x],表示如果其儿子有至少 y 个的值为 1,那么它的值也为 1

现在进行 Q 次操作,每次翻转编号在区间 [l,r] 内的叶结点的初值(0 变成 11 变成 0),然后询问有多少种为非叶结点设置参数的方案,使得根结点值为 1,对 10^9+2022 取模。

N,M,Q\leq 10^5

题解:

如果你是赛后做题,那么解题的关键或许是看到排行榜——有一车人过了这题,说明这题是水题。

或者是觉得这题看上去非常不可做,因为编号区间和树的形态并无关联,我们不可能用任何树上的数据解构解决此题。

无论如何,我们可以猜想:每个非叶结点对答案的贡献独立,幸运的是这是对的,证明并不困难,略。

于是首先树形 DP 算出每个非叶结点单独为黑色时的答案,然后用线段树维护总的答案即可,时间复杂度为 O(Q\log M+N+M)

IOI 2022 D2T2 Insects

题目大意:

现在有 N 个未知数 a_{1\ldots n},还有一台神秘机器,机器初始是空的,你可以进行下列三种操作:

你需要求出 a_{1\ldots n} 中出现次数最少的数的出现次数,设每种操作进行次数的最大值为 Q

--- ### 题解: 首先可以想到一个 $O(N^2)$ 次操作的算法:每次放一对数进去,就能知道它们是否相等。 还有一种 $O(N^2)$ 次操作的算法(记为青蛙算法):每次选择一个数,然后得到与它相等的所有数(加入一个别的数如果众数出现次数没有增加则说明不相等)。 还有一种 $O(N^2)$ 次操作的算法(记为垒球算法):每次选择当前剩下的所有不同的数各一个(时刻保持众数出现次数为 $1$ 即可),这样当某一次得到的不同的数的个数和上一次不同时,就知道出现次数最少的已经取完了。 综合青蛙算法和垒球算法,可以得到 $O(N\sqrt N)$ 的算法。 考虑垒球算法的扩展:如果保持众数出现次数始终小于等于 $C$,就可以得到每个数的前 $C$ 次出现,设不同的数有 $x$ 种,如果选出了恰好 $Cx$ 个数则说明出现次数最少的数也出现了 $\ge C$ 次,否则说明是 $<C$ 次。 所以可以二分,得到了 $O(N\log N)$ 的垒球算法。 然后发现这个二分的操作次数实际上可以变成 $O(N)$,因为如果二分之后发现答案 $\ge C$,那么此时已经放进机器里的就不用动了,可以看成总数大致减半;如果二分之后答案 $<C$,那么此刻不在机器里的数就可以全部扔掉了,总数也大致减半,根据等比数列求和这就是 $3N$ 次左右的。 然后一交获得了 $99$ 分的好成绩,下面使用你的独门技巧乱搞卡常即可。这里我的方法是在判断时只要某个时刻机器里已经有 $Cx$ 个数就直接退出循环,没必要加剩下的数,同时为了防卡,初始序列要随机重排。 ## IOI 2022 D2T3 Islands ### 题目大意: 有一张 $N$ 个点,$M$ 条边的有向图,你需要从点 $1$ 出发走一些边回到点 $1$,要求: - 一条边经过后就会反向,也就是下次经过必须是从反方向经过; - 不能连续经过同一条边。 构造一组方案,或说明无解。 $N\leq 10^5,\ M\leq 2\times 10^5

题解:

如果一个结点出度为 0,那么走到这里就寄了,所以可以删掉。

删掉之后可能会导致另一些点出度也变为 0,也要删掉,这个可以做一次拓扑排序,就相当于我们删掉了所有不能走到环的点。

现在我们断言,如果点 1出度 \ge 2,那么一定有解,下面给出构造。

事实上考虑下列结构:由于不存在零出度点,所以我们可以为每个点(除了 1)指定一条出边,这样整张图就形成了若干个基环树,以及一棵以 1 为根的树,如下图所示:

现在我们加上 1 的两条出边,那么有以下两种情况:

那么 1 的出度 \ge 2 的情况已经证完了,下面考虑 1 的出度 =1 的情况。

这时我们只能走这条出边,设为 1\to x,之后 1 就可以看出零出度点(只要在不走 x\to 1 这条反向边的情况下回到 1 就寄了),所以我们删去点 1,同样这也会导致连锁反应,还是用一个拓扑排序就可以把所有该删的点都删了。

在剩下的新图上,把 x 看成起点继续做即可,即如果 x 的出度 \ge 2 那么按照上面方法得到构造;如果 x 的出度 =1 那么再走它的出边,然后把 x 删掉,以此类推。

时间复杂度应该可以做到 O(N+M),不过我在实现时为了图省事,在记录边的序号以及删点的时候用到了 multisetmap,复杂度为 O(N+M\log M)

锐评环节

D1T1:比较简单的题,大概是想到单调性之后随便 DP 一下就行了,不过如果没想明白的话可能会用线段树去维护,其实是不用的。

D1T2:人类智慧题,有点看运气,运气好就想出来罢了,主要是到 X=26 那一步比较有难度,后面的使用其他进制并 DP 以及掐头去尾其实都不是很难。

D1T3:偏简单题,主要是想到用区间表示每个点的状态,后面的数据结构部分非常简单。

D2T1:诈骗题,猜出结论就没有难度了,而想到去猜这个结论其实并不很难(正如我前面所说,如果没有这种结论,这题是不可做的)。

D2T2:中档题,每一步优化都不是很难,但是只要少一步就做不出来,然后最后还要为了零点零几分在那卡常。

D2T3:思维简单,代码不太好写题,感觉这题口胡起来非常舒服。