Codeforces Round #749 (Div. 1 + Div. 2, based on Technocup 2022 Elimination Round 1) 题解

A - Windblume Ode

如果 \(n\) 个数加起来就是合数,那就是答案。

否则就是一个大于 \(2\) 的奇数(\(n\ge 3\)),那么 \(a\) 中必有一个奇数,删去它即可得到答案。

B - Omkar and Heavenly Tree

注意到 \(m<n\),那么必然存在一个点不会被作为 \(b\)

那么将这个点作为中心点,构造菊花图即可。

C - Omkar and Determination

如果一个位置“可退出”,那么一定可以推出它是空的。但非“可退出”位置可能是障碍也有可能是被挡住的空位,因此如果存在这样无法判断的情况即为 NO。

不难发现如果存在这样的情况:

?X
X?

那么右下的格子是无法判断的。于是做完了。

D - Omkar and the Meaning of Life

先确定 \(p_n\)。考虑将 \(i\) 看着高度为 \(i\) 的一个点,将一次询问视作将这些点“抬升”。那么我们将 \(p_n\) 抬升到相对前 \(n-1\) 个点抬升更多一些。从 \(0\) 开始枚举相对抬升大小 \(k\),如果出现回复为 \(0\),那么说明最大的 \(n\)\(p\) 相差 \(k\),于是 \(p_n=n-k+1\)。这部分花费不超过 \(n-1\) 次询问。

接下来我们找出 \(1\sim n-1\) 的位置。要找 \(i\) 的位置,可以将 \(p_n\) 抬升 \(i\),其他抬升 \(p_n\)。得到的回复即为 \(p_x=i\) 的位置 \(x\)。这部分也是 \(n-1\) 次询问。

E - Moment of Bloom

下面的度数为:点相连的奇数权值的边个数。

首先猜一个结论:跑出原图任意一个生成树直接对生成树求解不会更劣。

要证明可以感性理解:观察到,一次操作 \(a\to b\),只会使 \(a, b\) 两点的度数发生改变。然后我们相当于要对于这些奇数边集操作路径覆盖(每条边覆盖恰好一次)并且次数最小。一条路径可以恰好覆盖到两个奇度点,那么答案即为奇度点个数 \(/2\)。可以发现直接用树不会丢掉任何性质,于是就可以啦。

还有一点就是,对于一个连通图如果没有奇度点,那覆盖次数就是 \(1\)(一条欧拉回路),而树还不会有这种问题。

F - Defender of Childhood Dreams

一个挺难想的构造。考虑分治构造:对于区间 \([l,r]\),我们分成较均等的 \(k\) 个段,跨越部分之间用颜色 \(c\) 相连,每个段内部使用 \(c-1\) 种颜色递归求解。

观察到,如果我们想要找出 \(k\) 条颜色相同的边构成的路径是不可能的,因为这样必然只能在某一层递归的段之间跳,而这样的边数不超过 \(k-1\),因此正确性得证。

另一种想法是 \(k\) 进制。将 \(0\sim n-1\) 转成 \(k\) 进制,\(a\to b\) 的颜色设为两数的最高不同位。走一条边可以看作对当前数做增加操作,那不可能存在一位连续变化 \(k\) 次且其他位不发生变化。

不难发现答案为 \(\lceil\log_k n\rceil\)

H - Omkar and Tours

赛后发现这个 DS 实际上不算非常困难。原题问我们从一个点 \(x\) 经过容量不低于某个值 \(v\) 可达的最大点权,以及 \(x\) 到达最大点权对应的点所需路径上最大费用的最大值。

离线,然后第一问直接并查集就很好维护了。难点在于第二问,CF discuss 里头有点分的,甚至有 LCT 爆搞的。赛后口胡也想了一个相对简单但仍比标算复杂的做法:考虑对于每个连通块,维护块中每个颜色的点集及其两两构成路径最值的最大值。可以发现后者这个最大值有点像虚树,考虑每个颜色的点集可以和 ZJOI2019 语言那题一样用线段树搞,下标是 dfs 序,这样相邻两个计算路径最值即可。合并是用线段树合并,维护具体颜色用 unordered_map 启发式合并即可。直接用传统方法求路径最值,总复杂度是 \(O((n+q)\log^2 n)\)。经过万老爷指导了解到一种 \(O(n\log n)\) 预处理 \(O(1)\) 询问的 trick:按花费排序建 Kruskal 重构树,然后使用基于 RMQ 的 LCA 就行啦。

万老爷也胡了一个建两次 Kruskal 重构树的方法,具体的,在第一课树上跑出 dfs 序,然后在第二棵数上找到一个最低点满足子树完全恰好包含对应点集,也可以 \(\log \sim \log^2\) 求解,不过相对标算仍然复杂了些。

注意到这样的做法完全没有利用查询颜色为最大值的性质,也不好写。考虑可以只维护一个最大的颜色的最值,然后观察到合并两个连通块时,假如两边最大值不同可以直接选两个中的较大值,而如果两个最大值相同,考虑到新加入的部分就是两个虚树包含到的部分中间相连的路径。注意如果我们任意取出两侧最大点集的分别一个,更新最值,那一定可以将这块新的部分覆盖。那么维护整个点集就没有必要了。同理对于一次查询,我们也可以取出任意一个点将询问位置到虚树内部区域完全覆盖。

最后随便一个阳间的链上最值的方法都可以在 \(O((n+q)\log n)\) 时间内求解。做法简化了很多。

posted @ 2021-10-19 21:06  -Wallace-  阅读(208)  评论(0编辑  收藏  举报