2024.2 做题记录
164. P7712 [Ynoi2077] hlcpq
考虑暴力显然是建图跑 tarjan。
但是连通性相关不能优化建图,因为可能影响答案。
考虑 tarjan 的过程。发现我们要找出:
- 一个点邻居中所有未被访问过的点
- 一个点邻居中访问过的点的 dfn 的 \(\min\)
考虑主席树预处理出包含每个点的区间的编号。那么第一个任务可以主席树上二分。第二个任务就访问过所有没访问过的点后求个区间 \(\min\) 即可。记得访问过一个点要更新。
165. CF1398G Running Competition
傻逼题。容易转化成求 \(\{x | \exists i, j, a_i - a_j = x\}\)。减法卷积即可。
记得减法卷积是翻转其中一个多项式再加法卷积。
166. CF1381C Mastermind
考虑贪心。对于前 \(x\) 个元素,我们贪心地让出现次数最多的一些元素成为对应位置相等的。
然后我们考虑构造原序列每个位置都不同但是出现过的数最最多。就是每次取两个出现次数最大的数配对。若剩下三个不同的数则让三个配对。
167. P9601 [IOI2023] 最长路程
只讨论 \(d = 1\)。
发现若图不连通则一定只有两个连通块,并且两个连通块都是完全图。
那么若图连通则答案一定是 \(n\)。考虑构造性证明。
一个思路是增量维护答案,也就是维护一条链,每次加一个点。但是发现这样做十分困难,因为需要二分加的位置,这个询问次数省不下来。
更好的思路是维护两条链,那么加一个点变得非常简单。最后合并时若两条链的链头链尾之间没有边那么由图性质可得这两条链都是环,两次二分出中间连的一条边,断环为链即可。
发现这样询问次数至少是 \(2n\)。发现我们可以三次询问加两个点,稍稍分类讨论下即可。那么询问次数为 \(1.5n + 2 \log n + O(1)\),可以通过。
168. CF1918E ace5 and Task Order
世纪难题。
首先我们考虑先固定 \(x\),比如让 \(x = a_1\)(重复问 \(1\) 直到回答为 =),那么此时我们可以知道任意一个 \(a_i\) 和 \(a_1\) 的大小关系(问一次 \(i\) 再问一次 \(1\)),并且可以知道 \(a_i\) 的具体值。
那么剩下的数被分成了两个集合,一个 \(< a_1\) 一个 \(> a_1\)。发现我们可以对这两个集合递归地做上面的过程。递归时传需要求的位置集合和值域 \([l, r]\) 即可。
问题在于询问次数没有保障。考虑每次递归时从当前集合中随机一个数作为分界点。期望询问次数 \(O(n \log n)\)。\(40n\) 的次数限制很宽松所以能过。
169. CF1918F Caterpillar on a Tree
考虑 \(k = 0\) 就是 \(2(n - 1)\) 减去最大深度。然后我们考虑每次 \(2\) 操作对答案的增量。
考虑连续访问两个叶子,若把走到 LCA 再走下去的操作换成跳根,那么增量为 \(x - y\),其中 \(x\) 为 LCA 深度,\(y\) 为前一个叶子到 LCA 的距离。钦定每棵子树都是深度最深的叶子最后访问。
时间复杂度 \(O(n \log n)\)。
170. P10144 [WC/CTS2024] 水镜
WC2024 被打爆了,呜呜。我赛时会这题 \(8\) 分指数级暴力,哈哈。真不知道自己在干嘛。
下文令 \(T = 2L\)。
考虑如何判定一个序列 \(a\) 是否合法。考虑先枚举一个 \(T\)。因为要求 \(r_i < r_{i + 1}\),考虑讨论相邻两项的取值:
- 若 \(a_i < a_{i + 1}\) 则 \(r_i = a_i, r_{i + 1} = a_{i + 1}\) 可行,也就是若 \(a_i \ge a_{i + 1}\) 则 \(r_i = a_i, r_{i + 1} = a_{i + 1}\) 不可行;
- 若 \(a_i > a_{i + 1}\) 则 \(r_i = T - a_i, r_{i + 1} = T - a_{i + 1}\) 可行,也就是若 \(a_i \le a_{i + 1}\) 则 \(r_i = T - a_i, r_{i + 1} = T - a_{i + 1}\) 不可行;
- 若 \(a_i + a_{i + 1} < T\) 则 \(r_i = a_i, r_{i + 1} = T - a_{i + 1}\) 可行,也就是若 \(a_i + a_{i + 1} \ge T\) 则 \(r_i = a_i, r_{i + 1} = T - a_{i + 1}\) 不可行;
- 若 \(a_i + a_{i + 1} > T\) 则 \(r_i = T - a_i, r_{i + 1} = a_{i + 1}\) 可行,也就是若 \(a_i + a_{i + 1} \le T\) 则 \(r_i = T - a_i, r_{i + 1} = a_{i + 1}\) 不可行。
也就是说:
- 若 \(a_i \le a_{i + 1}\) 且 \(a_i + a_{i + 1} \le T\) 则 \(r_i\) 必须取 \(a_i\);
- 若 \(a_i \le a_{i + 1}\) 且 \(a_i + a_{i + 1} \ge T\) 则 \(r_{i + 1}\) 必须取 \(a_{i + 1}\);
- 若 \(a_i \ge a_{i + 1}\) 且 \(a_i + a_{i + 1} \le T\) 则 \(r_{i + 1}\) 必须取 \(T - a_{i + 1}\);
- 若 \(a_i \ge a_{i + 1}\) 且 \(a_i + a_{i + 1} \ge T\) 则 \(r_i\) 必须取 \(T - a_i\)。
若这个序列不存在一组 \(r\) 则一定能从上述四个条件得出矛盾。有三种矛盾:
- \(a_i = a_{i + 1}, a_i + a_{i + 1} = T\);
- \(a_{i - 1} \le a_i, a_{i - 1} + a_i \ge T, a_i \ge a_{i + 1}, a_i + a_{i + 1} \ge T\);
- \(a_{i - 1} \ge a_i, a_{i - 1} + a_i \le T, a_i \le a_{i + 1}, a_i + a_{i + 1} \le T\)。
考虑不枚举 \(T\) 怎么判合法性。考虑第二种矛盾,相当于若存在 \(i\) 使得 \(a_{i - 1} \le a_i, a_i \ge a_{i + 1}\),那么 \(T > \min(a_{i - 1} + a_i, a_i + a_{i + 1})\),否则就会产生矛盾;类似地考虑第三种矛盾,若存在 \(i\) 使得 \(a_{i - 1} \ge a_i, a_i \le a_{i + 1}\),那么 \(T < \max(a_{i - 1} + a_i, a_i + a_{i + 1})\)。
也就是说对于一些位置有 \(T \in (l_i, r_i)\) 的限制,若最后这些区间交出来不是空集(即 \(\max l_i < \min r_i\))那么就合法。这时候发现第一种矛盾不需要考虑,因为若区间交出来不是空集则 \(T\) 有无限个取值。
回到原题,考虑计算合法的子区间个数。发现对于一个左端点,合法的右端点一定是一段区间。直接二分右端点再判定即可。判定就是判区间 \(\max l_i\) 是否 \(< \min r_i\)。
总时间复杂度 \(O(n \log n)\)。
171. P9602 [IOI2023] 足球场
考虑描述合法足球场的形态,发现是若干个连续的行,每个行被选的是一个区间,且区间先变大后变小,并且这些区间两两为包含关系。
考虑钦定足球场必须全部包含第 \(x\) 列,这样可以设计 dp,\(f_{l, r}\) 为包含 \([l, r]\) 行的足球场面积最大值,那么 \(f_{l, r} = \max(f_{l, r - 1}, f_{l + 1, r}) + len\),其中 \(len\) 为 \([l, r]\) 行包含第 \(x\) 列的区间交集长度。就是往外扩充一行,并且贪心地使其最大。
发现 dp 状态已经是 \(O(n^3)\) 了。考虑从状态优化发现有用的最后能对答案有贡献的状态只有 \(O(n^2)\) 个,并且每个非障碍格子 \((r, x)\) 能确定一个 \(l\),就是最上方的顶到障碍的行。那么直接设 \(f_{r, x}\) 就行了。
至于转移,被 \(r\) 扩展是简单的。被 \(l\) 扩展,就找到最近的左(或右)的障碍,从那个格子转移过来即可。时间复杂度 \(O(n^2)\)。
172. CF1927G Paint Charges
看到 \(n \le 100\) 考虑 \(O(\text{poly}(n))\) dp。发现从左向右决策,因为一个点可以向左或向右覆盖,所以需要记最靠左的未覆盖的位置 \(j\) 和最靠右的已覆盖位置 \(k\),状态就是 \(f_{i, j, k}\),dp 最小的覆盖次数。
转移的讨论很简单。考虑不覆盖还是向左或向右覆盖,若向左或向右覆盖看能否覆盖到 \(j\) 或 \(k\)。这样转移是 \(O(1)\) 的。总时间复杂度 \(O(n^3)\)。
173. CF1270E Divide Points
考虑按奇偶性分组。若不是全奇也不是全偶就直接输出。若全奇可以通过把全部 \(x\) 坐标 \(+1\) 变成全偶。
若全偶,考虑若 \(x\) 坐标是全奇可以把全部 \(x, y\) 坐标 \(+1\) 变成全偶。若 \(x\) 坐标不是全奇也不是全偶那么直接把全奇(或全偶)的输出,因为距离相等的不可能又有到同类又有到异类的,因为 \(x^2 + y^2\) 若 \(x, y\) 都是奇数则 \(\bmod 4 = 2\),若都是偶数则 \(\bmod 4 = 0\)。若 \(x\) 坐标全偶就把 \(x, y\) 坐标都除以 \(2\) 继续递归做。
时间复杂度 \(O(n \log V)\)。
174. CF1286C2 Madhouse (Hard version)
可以把限制看成 \(0.75n^2\)。发现 \(0.75n^2 = 0.5n^2 + 2 \times 0.5 (\frac{n}{2})^2\)。这启发我们询问一次 \([1, n]\) 和两次长度为 \(\frac{n}{2}\) 的区间。
不妨问 \([1, n], [1, \frac{n}{2}], [1, \frac{n}{2} + 1]\) 试试。注意到把 \([1, \frac{n}{2} + 1]\) 得到的集合除去 \([1, \frac{n}{2}]\) 中的元素,得到的是左端点在 \([1, \frac{n}{2} + 1]\),右端点为 \(\frac{n}{2} + 1\) 的子串,可以通过这些串中长度为 \(i\) 除去长度为 \(i - 1\) 的串剩下的字符求出原串 \([1, \frac{n}{2} + 1]\) 中的字符。接下来的任务是求 \([\frac{n}{2} + 2, n]\) 中的字符。
考虑 \([1, n]\) 的集合中所有长度为 \(2\) 的串,除了已知的 \(s[1, \frac{n}{2} + 1]\),剩下的只有 \(s_n\) 出现 \(1\) 次,\(s[\frac{n}{2} + 2, n - 1]\) 都是出现 \(2\) 次。那么出现次数为奇数的字母就是 \(s_n\)。
再考虑 \([1, n]\) 中所有长度为 \(3\) 的串。除了已知的 \(s[1, \frac{n}{2} + 1]\) 和 \(s_n\),剩下的只有 \(s_{n - 1}\) 出现 \(2\) 次,\(s[\frac{n}{2} + 2, n - 2]\) 都是出现 \(3\) 次。那么出现次数 \(\bmod\ 3 = 2\) 的字母就是 \(s_n\)。
以此类推,所有长度为 \(i\) 的串中,除去已知的,只有 \(s_{n - i + 2}\) 出现 \(i - 1\) 次,其他未知的都出现 \(i\) 次。所以出现次数 \(\bmod\ i = i - 1\) 的字母就是 \(s_{n - i + 2}\)。这样可以确定 \([\frac{n}{2} + 2, n]\) 的部分。
总共使用 \(3\) 次询问,总子串个数 \(\approx 0.75n^2\)。
175. CF460D Little Victor and Set
发现可以只考虑 \(|S| \le 4\) 的情况,更大的跨度会更大,不优。
可以特判 \(r - l + 1\) 比较小的情况,直接枚举子集。
发现 \((2k) \oplus (2k + 1) = 1, (4k) \oplus (4k + 1) \oplus (4k + 2) \oplus (4k + 3) = 0\)。若 \(r - l + 1\) 足够大就一定能找到这样的 \(k\)。
至于 \(|S| = 3\),可以考虑让 \(l\) 为最小数,设 \(2^t\) 为 \(l\) 的最高位,那么最大数 \(x = 3 \times 2^t\) 时最优。不难分讨证明。
176. CF1918G Permutation of Given
考虑增量构造答案,每次加两个数。设原序列为 \([\ldots, a, b]\),新序列为 \([\ldots, a, b, x, y]\)。发现需要满足 \(\{a + x, b + y, x\} = \{a, x, y\}\)。容易发现令 \(x = -b, y = a - b\) 满足条件。
爆搜得出 \(n = 2, n = 7\) 的一组解(\(n = 3\) 或 \(n = 5\) 无解)即可。
177. P10145 [WC/CTS2024] 线段树
若一个结点 \([l_i, r_i)\) 已知就连边 \((l_i, r_i)\),那么子集满足条件当且仅当每对 \((L_i, R_i)\) 都连通。
考虑在树形结构上 dp。发现若 \(l, r\) 不连通,设 \(l\) 所在连通块点编号最大值为 \(i\),那么 \(r\) 所在连通块点编号最小值 \(> i\)。
于是设 \(f_{u, i}\) 为 \(u\) 结点 \(l, r\) 不连通,\(l\) 所在连通块点编号最大值为 \(i\) 且满足子树中所有条件的方案数(在子树中定义为 \(L_i, R_i\) 至少有一个在子树中),\(g_u\) 为 \(u\) 结点 \(l, r\) 连通且满足子树中所有条件的方案数。考虑 \(l, r\) 之间是否连边,就有转移(设 \(v\) 为 \(u\) 的左儿子,\(w\) 为 \(u\) 的右儿子):
第四种转移要注意,\([i + 1, j]\) 的部分会和外界不连通,所以不能存在 \((L_i, R_i)\) 使得一个在 \([i + 1, j]\) 里面一个不在。然后转移到 \(f_{u, i}\) 或 \(f_{u, j}\) 都是满足状态定义的,可以任意转移到一个。
考虑异或哈希,对每对 \((L_i, R_i)\),让 \(a_{L_i}, a_{R_i}\) 都异或上一个随机数,然后对 \(a\) 做一遍前缀异或,那么第四种转移的充要条件为 \(a_i = a_j\)。
此时我们发现 \(a_i\) 相等的状态可以放在一起考虑。若把 \(i\) 改写成 \(a_i\),那么:
线段树合并维护即可。在叶子处合并 dp 值,若走到了非公共结点就打个乘法 tag。
时间复杂度 \(O(n \log n)\),默认 \(n, m\) 同阶。
178. [ABC340G] Leaf Color
对每种颜色的点建虚树,树形 dp 即可。设 \(f_u\) 为 \(u\) 子树内以 \(u\) 为根的连通块个数。初值 \(f_u = 1\) 当且仅当 \(u\) 是关键点。
统计答案时,若连通块的根是非关键点,那么要钦定它和至少两棵子树相连。减去和至多一棵子树相连的方案数即可。
179. CF1909G Pumping Lemma
考虑删除 \(s\) 中非 \(s, t\) 公共后缀的部分(在 \(t\) 中也删除这部分),那么 \(x\) 必然是 \(y'y^a\) 的形式,其中 \(y'\) 为 \(y\) 的一段后缀。
已知 \(|y^{k - 1}| = m - n\),考虑枚举 \(y\) 的长度 \(l\)。设 \(t[l + 1, m]\) 和 \(t\) 的 lcp 为 \(k\)。那么 \(|x|\) 需要满足 \(|x| \le k - (m - n)\),取值个数为 \(\max(k - (m - n) + 1, 0)\)。加和即可。
180. CF1928F Digital Patterns
为什么我场上被卡常了。
转化题意,将 \(a, b\) 差分,答案为在 \(a, b\) 选出相同长度的不含 \(0\) 的子段方案数。
设 \(a\) 选出长度为 \(i\) 的不含 \(0\) 的子段方案数为 \(x_i\),\(b\) 选出长度为 \(i\) 的不含 \(0\) 的子段方案数为 \(y_i\)。答案为 \(\sum x_i y_i\)。考虑线段树维护这个东西。
一个 \(a\) 中长度为 \(l\) 的极长子段会给 \(\forall k \in [1, l]\) 的 \(x_k\) 贡献 \(k - l + 1\)。\(b\) 同理。\(k + 1\) 和 \(-l\) 是独立的,先考虑 \(-l\) 这部分。也就是要支持 \(x_i \gets x_i + di\) 或 \(y_i \gets y_i + di\)。
只考虑修改 \(x\),\(y\) 是对称的。拆式子:\(\sum (x_i + di) y_i = \sum x_i y_i + d \sum i y_i\)。再维护 \(\sum i x_i\) 和 \(\sum i y_i\) 就可以完成 \(\sum x_i y_i\) 的修改。\(\sum i x_i\) 的修改是容易的,考虑 \(\sum i (x_i + i) = \sum i x_i + \sum i^2\),后者显然可以 \(O(1)\) 求的。
还要支持 \(x_i \gets x_i + d\) 或者 \(y_i \gets y_i + d\)。继续拆式子:\(\sum (x_i + d) y_i = \sum x_i y_i + d \sum x_i\)。再维护 \(\sum x_i, \sum y_i\) 即可。
于是线段树每个结点维护 \(5\) 个值:\(\sum x_i y_i, \sum x_i, \sum y_i, \sum i x_i, \sum i y_i\) 和 \(4\) 种懒标记即可。
差分后区间加变成了单点修改。考虑对 \(a, b\) 分别开个 set 维护非 \(0\) 极长连续段。显然单点修改只会加入或删除 \(O(1)\) 个段,讨论下就行了。
时间复杂度 \(O((n + q) \log n)\),但是线段树的常数巨大,实现精细点就能过了。
181. CF1931G One-Dimensional Puzzle
什么 [ABC336G] 16 Integers 究极弱化版。
把元素 \(1\) 看成 \(01\),元素 \(2\) 看成 \(10\),元素 \(3\) 看成 \(11\),元素 \(4\) 看成 \(00\)。则转化为统计长度为 \(2\) 的子串 \(xy\) 出现次数为 \(c_{xy}\) 的 \(01\) 串个数。
把子串 \(xy\) 看成 \(x \to y\) 的一条有向边,那么这是一个点数为 \(2\) 的欧拉路径计数问题,可以 BEST 定理解决,但是不需要。
有解的必要条件是 \(|c_{01} - c_{10}| \le 1\)。若 \(c_{01} = c_{10}\) 那么 \(01\) 串开头和结尾的字符相同。若以 \(0\) 开头和结尾,相当于把 \(c_{00} + c_{01} + 1\) 个 \(0\) 分成 \(c_{01} + 1\) 份,\(c_{10} + c_{11}\) 个 \(1\) 分成 \(c_{10}\) 份,每份非空,根据插板法可得方案数为 \(\binom{c_{00} + c_{01}}{c_{01}} \binom{c_{10} + c_{11} - 1}{c_{10} - 1}\)。以 \(1\) 开头和结尾类似。
若 \(c_{01} = c_{10} + 1\),那么以 \(0\) 开头,以 \(1\) 结尾。相当于把 \(c_{00} + c_{01}\) 个 \(0\) 分成 \(c_{01}\) 份,\(c_{11} + c_{01}\) 个 \(1\) 分成 \(c_{01}\) 份,方案数为 \(\binom{c_{00} + c_{01} - 1}{c_{01} - 1} \binom{c_{11} + c_{01} - 1}{c_{01} - 1}\)。
\(c_{10} = c_{01} + 1\) 的情况是类似的。注意特判 \(c_{10} = c_{01} = 0\),这种情况只能是全 \(0\) 或全 \(1\),所以 \(c_{00}\) 和 \(c_{11}\) 不能都非 \(0\)。
时间复杂度 \(O(T + \sum c_i)\)。
182. [ARC167E] One Square in a Triangle
感觉没啥好说的。
先钦定一个点是 \((0, 0)\)。然后直接构造。\(S\) 为偶数时钦定底边长度为 \(2\),其他两个点是 \((2, 0), (\frac{S}{2}, \frac{S}{2})\);\(S\) 为奇数时考虑利用 \((3, 1)\)。那么另一个点就是 \((\frac{S - 3}{2}, \frac{S - 1}{2})\)。\(S \in \{1, 2, 3, 5, 7\}\) 时无解。
183. QOJ3307 Query on a Tree 17
考虑求出 dfs 序的带权中点。因为最浅的重心子树大小 \(> \frac{n}{2}\) 所以它一定被重心的子树包含。倍增向上跳,树剖套线段树维护 \(a_i\) 即可。
184. CF1889E Doremy's Swapping Trees
神秘。
有连通块相同的限制。考虑若选了 \(T_1\) 中的边 \((u, v)\),那么 \(T_2\) 上 \(u \to v\) 的路径上的边都要选。
考虑连这样的有向边。这部分可以倍增优化建图或树剖优化建图,不是重点。
缩完点后是个 DAG。一次操作就是选择一个没有出度的导出子图,把点里面的边和点与点之间的边翻转方向。
通过某种神秘力量,可以知道答案就是 \(2^{cnt}\),其中 \(cnt\) 是强连通分量个数。特别地要减去点数 \(= 2\) 的强连通分量,因为此时两条边完全相同,交换后没有影响。
185. QOJ1437 The Destruction of the Crystals
经典套路:网格行与列连边。对于每个炸弹将它的行和列连边。那么一个有环的连通块肯定可以把全部点炸掉。
若一个宝石的行和列在同一个连通块,那么炸到这个连通块一定能炸掉这个宝石。否则将其累加至 \(c_i\) 表示一个点挂的宝石个数。
若连通块是一棵树,那么舍弃一个叶子就能把剩下的炸完。枚举舍弃的这个叶子即可。
186. QOJ1436 Split in Sets
位运算操作的题有一个套路,就是从高位往低位考虑。
设 \(1\) 的数量为 \(c\)。若 \(c < m\) 那么肯定是这一位为 \(1\) 的数单独占一个盒子。因为考虑一个 \(0\) 进来,这一位 \(1\) 就没了,损失更大。同理若 \(c \ge m\) 肯定是这一位为 \(0\) 的全部占一个盒子,把它们合并。
最后第二类斯特林数算方案数即可。注意原题盒子两两区分,第二类斯特林数算的是盒子互不区分的方案。所以乘一个 \(m!\) 即可。
187. QOJ833 Cells Blocking
只能向下或向右走的网格连通性问题。考虑找出最靠左下的一条路径 \(P\) 和最靠右上的一条路径 \(Q\)。
若选了 \(P\) 和 \(Q\) 的交集那么 \((1, 1)\) 已经无法到 \((n, m)\) 了。
若选了在 \(P\) 不在 \(Q\) 的格子 \((x, y)\),考虑找出 ban 掉这个格子后新的 \(P'\)。作一条斜率为 \(1\) 的直线,沿着这个直线向上找到第一个和 \((1, 1), (n, m)\) 连通的格子,那么 \(P'\) 必定经过 \((x, y)\)。求出 \(P'\),那么 ban 掉 \(P'\) 和 \(Q\) 的交集的格子是可行的。
需要避免算重。第二部分因为总方案数是 \(O((n + m)^2)\) 的所以可以拿个哈希表来存。
188. QOJ1844 Cactus
妙妙题。
考虑先把奇度点删了,然后递归操作直到所有点都是偶数点。此时必须要进行一次 \(2\) 操作。
然后建圆方树,从叶子的方点父亲开始不断删环。因为是叶子所以这个环至多存在一个点使得现在除了这个点,其他点只存在于这个环。设环为 \(p_0 \to p_1 \to \cdots \to p_m \to p_0\),其中 \(p_0\) 为存在于两个或以上的环的点(若不存在就随便选一个)。因为 \(p_0\) 可以留给父亲所以不用管。
然后依次剥环,即依次操作 \(p_1, p_2 + n, p_3, p_4 + n, \ldots\) 一直到 \(m\)。然后再操作 \(p_1 + n\),若 \(m\) 为奇数则操作 \(p_m + n\) 否则操作 \(p_m\)。那么这样整个环都被删了,连通环上 \((u, u + n)\) 的边,并且不会影响到其他边。自底向上这么做即可。
189. [AGC012E] Camel and Oases
容易发现跳跃次数为 \(O(\log V)\)。考虑对于跳跃 \(k\) 次后的限制 \(\left\lfloor\frac{V}{2^k}\right\rfloor\),对每个点预处理出不再跳跃能到达的最左和最右的点 \([l_{k, i}, r_{k, i}]\)。
于是问题变成了,从第 \(i\) 个区间集选择一个区间 \([a_i, b_i]\),若这些区间的并集是 \([1, n]\),那么这种方案会使得 \([a_0, b_0]\) 能够到达全部点。
\([a_0, b_0]\) 看起来比较烦。先把第 \(0\) 个区间集扔掉。设当前的区间集的集合为 \(U\),\(f_S\) 为从 \(S\) 中的每个区间集选出一个区间能覆盖的最大前缀右端点,同时设 \(g_S\) 为能覆盖的最大后缀的左端点。\(f_S, g_S\) 可以状压 dp 求出。枚举覆盖了一段前缀的集合 \(S\),设 \(T = U \setminus S\),那么 \(T\) 覆盖了一段后缀。
若 \(f_S + 1 \ge g_T\),那么 \(U\) 满足从每个区间集选出一个区间能覆盖 \([1, n]\),此时就是全部 Possible;否则需要满足 \([f_S + 1, g_T - 1] \subseteq [a_0, b_0] = [l_{0, f_S + 1}, r_{0, f_S + 1}]\)。若 \(r_{0, f_S + 1} + 1 \ge g_T\) 那么 \([l_{0, f_S + 1}, r_{0, f_S + 1}]\) 就能到达全部点。
时间复杂度 \(O((n + V) \log V)\)。
190. CF1658E Gojou and Matrix Game
很经典的博弈问题,模拟赛被薄纱了。/ll
考虑建无向图,能到达的点之间连边。那么我们发现当前的先手不会走到更小的格子,因为当前的后手可以移回去从而对他的得分造成正贡献。
所以不妨给边定向,值小的连向值大的。那么就转化成了有向图博弈问题,到达出度为 \(0\) 的点输。直接按拓扑序倒序递推每个点是必胜还是必败态即可。
对于这题先套路地曼哈顿转切比雪夫,然后查询 \(x\) 或 \(y\) 坐标的一段区间是否存在必败态即可。可以用树状数组维护。
191. CF985G Team Players
直接容斥,钦定三个点中存在一些边。
\(0\) 条边是简单的,枚举 \(j\),\(i, k\) 可以直接计算和。
\(1\) 条边就枚举是哪条边,讨论第三个点在哪个范围内即可。
\(2\) 条边就枚举连了两个点的点是哪个。树状数组维护第三个点的取值。
\(3\) 条边就是三元环计数。
192. P5074 Eat the Trees
考虑插头 dp,把每个格子是否向下延伸,左边的格子是否向右延伸记入状态。
转移讨论上面的格子是否向下延伸,左边的格子是否向右延伸即可。
193. 「JOISC 2018 Day 4」野猪
直观感受一下发现两点之间有用的路径不会很多。具体地,我们找到如下四条路径(\(s, t\) 表示出边):
- \(s_1 \to t_1\),最短路。
- \(s_2 \to t_2\),次短路,\(s_1 \ne s_2, t_1 \ne t_2\)。
- \(s_3 \to t_3\),次短路,\(s_3 \ne s_1, t_3 \ne t_2\)。
- \(s_4 \to t_4\),次短路,\(s_4 \ne s_2, t_4 \ne t_1\)。
那么我们任意两点间只会用到上面 \(4\) 条路径。对于 \(q = 1\),可以直接 dp,设 \(f_{i, j}\) 为上一条路径是第 \(j\) 条的最短长度。
求上面 \(4\) 条路径考虑对边跑最短路。朴素地跑是 \(O(m^3)\) 的。但是因为这是边的点权最短路,考虑从一条入边进入 \(u\) 点,那么下一次进入 \(u\) 点只用更新这条入边的反向边。这部分时间复杂度降到 \(O(m^2 \log m)\)。
有修改就考虑动态 dp 即可,线段树每个叶子结点维护一个 \(4 \times 4\) 的矩阵表示前面用第 \(i\) 条路径,后面用第 \(j\) 条路径的最短长度。这部分时间复杂度为 \(O(4^3 q \log l)\)
194. P10163 [DTCPC 2024] 平方树
我们应该先把这个森林变成树,那么每个点加出边必须加点。
考虑找到一个合法连通块(不存在一个出度不是完全平方数的连通块),把其他不合法连通块连向这个连通块。
这样只剩下至多一个不合法连通块,然后把这个不合法连通块连向合法连通块。
考虑若不是一棵树那么每个连通块都合法,找到出度为 \(0\) 的点串成一条链即可。
195. QOJ1856 Interval
考虑每个数轴上的点,记覆盖它的区间编号为 \(i_1, i_2, \ldots, i_m\)。设 \(f_{l, r}\) 为 \(|\bigcup\limits_{i = l}^r [L_i, R_i]|\)。考虑容斥,对于 \(l \le i_j \le r\),对 \(f_{l, r}\) 加 \(1\);对于 \(l \le i_j, i_{j + 1} \le r\),对 \(f_{l, r}\) 减 \(1\)。那么询问就是矩形求和。
显然我们不可能对每个点都做一遍。那么对于一个区间 \([L_i, R_i]\),可以 \(l \le i \le r\),\(f_{l, r}\) 加上这个区间的长度;对于第二种贡献,考虑之前和 \([L_i, R_i]\) 有交集且编号最大的一些线段 \(j\),那么对于 \(l \le j, i \le r\) 对 \(f_{l, r}\) 减去交集的长度。可以使用类似颜色段均摊的东西维护。
那么现在题目被转化成了矩形加矩形求和。扫描线即可。
196. QOJ7881 Computational Complexity
差分,设 \(n = xk\),其中 \(\gcd(2 \times 3 \times 5 \times 7, x) = 1\),那么当 \(x \ge 14\) 时 \(f'(n), g'(n)\) 没有值。
所以只有 \(O(\log^4 V)\) 个位置有值。求出这些有值的位置,询问就查前缀和即可。
197. CF1930E 2..3...4.... Wonderful! Wonderful!
傻了,直接找充要条件就行了。
套路地考虑一个子序列是否能被生成。
把是否在子序列看成一个 \(01\) 串,那么无解当且仅当正数第 \(k\) 个 \(0\) 和倒数第 \(k\) 个 \(0\) 中间没有 \(1\)。
所以就枚举长度,随便插板法算一下。
198. P6167 [IOI2016] shortcut
模拟赛 T2。很有趣的题。
考虑二分答案 \(p\)。设在 \(x, y\) 加边,那么对于任意数对 \((i, j)\),\(i < j\),下面两个条件至少满足一个:
- \(b_i + b_j + a_j - a_i \le p\)
- \(b_i + b_j + |a_i - a_x| + |a_j - a_y| + m \le p\)
考虑曼哈顿距离转切比雪夫,第二个条件化为 \(b_i + b_j + \max(|a_j + a_i - X|, |a_j - a_j - Y|) + m \le p\)。也就是:
- \(X \in [a_i + a_j + b_i + b_j - p + m, a_i + a_j - b_i - b_j + p - m]\);
- \(Y \in [a_i - a_j + b_i + b_j - p + m, a_i - a_j - b_i - b_j + p - m]\)。
于是求出 \(X, Y\) 的上下界,就可以双指针判有没有满足这样条件的一对 \((x, y)\)。
考虑枚举 \(j\),算满足 \(b_i + b_j + a_j - a_i > p\) 的 \(b_i - a_i\) 和 \(a_i + b_i\) 的最大值。前者直接取最大值即可,因为若连最大值都不满足 \(b_i + b_j + a_j - a_i > p\) 那么就全部都不满足了。
考虑算后者。可以维护一个 \(b_i - a_i\) 递减的单调队列,每次能弹出队头就尽量弹,并且边弹出队头取 \(a_i + b_i\) 的最大值。因为考虑一对 \((x, y)\),\(x < y\),若 \(b_x - a_x \le b_y - a_y\) 则 \(a_x + b_x \le a_y + b_y\)。所以若 \(b_i - a_i\) 不递减,那么前面的元素一定没有贡献。
所以不用二维数点,时间复杂度 \(O(n \log V)\)。
199. LOJ2834 「JOISC 2018 Day 2」修行
考虑若已求出钦定 \(k\) 个升高的排列数量 \(f_k\),那么二项式反演就可以求出恰好 \(k\) 个升高的排列数量 \(g_k\),即:
考虑求 \(f_i\)。相当于钦定原序列构成了 \(n - k\) 个上升段。相当于把 \(n\) 个数分成 \(n - k\) 个互相区分的集合,每个集合内部升序排序就是上升段。所以:
直接 NTT 求一行的斯特林数可以通过 P5825 排列计数,但是这题的模数只能 MTT。考虑用斯特林数的通项公式展开,把 \(f_i\) 代入 \(g_k\):
最后一步用到了这个恒等式:\(\sum\limits_i \binom{i}{a} \binom{n - i}{b} = \binom{n + 1}{a + b + 1}\)。组合意义即为考虑 \(n + 1\) 个物品中选 \(a + b + 1\) 个,枚举第 \(a + 1\) 个物品的位置,加上左边选 \(a\) 个的方案数乘上右边选 \(b\) 个的方案数。
直接快速幂计算 \(i^n\) 就是 \(O(n \log n)\) 的,也可以线性筛做到 \(O(n)\)。
200. 2024.2.20 模拟赛 T3 图图(graph)
考虑若我们找出了所有强连通分量,那么我们可以逐个剥强连通分量。每次若 \(|A_1| > 1\) 则它们肯定能到达剩下的全部点(因为这个分量包含左部点和右部点),所以可以直接删除。否则我们找到极长的一段前缀 \(A_1, A_2, \ldots, A_i\),满足 \(|A_1| = |A_2| = \cdots = |A_i| = 1\) 且它们的点在同一侧。那么它们不能互相到达,且都能到达剩下的点。计算答案后也可以删去。
考虑怎么找强连通分量。一个思路是把它补成一个竞赛图后兰道定理找。要补成竞赛图,可以把两侧的点分别按照出度排序,然后后面的点连向前面的点。这样不会改变强连通分量,因为它们是一个拓扑序。
201. 2024.2.21 模拟赛 T1 决斗(duel)
做题做傻了属于是。
考虑找一些能获胜的充要条件。可以尝试剥最大值。每次找到最大值的位置 \(p\),不妨设 \(i < p\),那么 \(i\) 能获胜当且仅当:
- \(i\) 能打败 \([1, p - 1]\);
- \(a_i + p - 2 \le a_p\)。
这是一个递归判定的子问题。由此可以 dp,设 \(f_{l, r, x, y}\) 表示考虑在 \([l, r]\) 中的人,\(a_i \in [1, x]\),并且获胜的充要条件是 \(a_i\) 能打败所有 \([l, r]\) 中的人且 \(a_i \ge y\)。转移枚举最左边的最大值位置和它的值即可。
202. QOJ837 Giant Penguin
考虑随便建出一棵生成树后点分治。那么跨过不同子树的非树边的路径只有 \(O(k)\) 种。非树边包含的点也只有 \(O(k)\) 种。称这些点为特殊点。对这些特殊点暴力跑 bfs。还要 bfs 这些分治中心。
那么删去这些点后跨过不同子树的路径都已经被考虑。
考虑如何处理修改和询问。把一个路径拆成两部分,即一个点到特殊点的距离和特殊点到另一个点的距离。然后修改就更新中转点,询问对所有中转点取 \(\min\) 即可。时间复杂度 \(O((n + q) k \log n)\)。
203. [AGC045C] Range Set
考虑找到题目操作的逆操作。相当于每次找到长度 \(\ge A\) 的子串赋成 \(1\),或者长度 \(\ge B\) 的子串赋成 \(0\)。那么一个串能被得到,当且仅当能通过这些操作变成全 \(0\)。因为 \(0, 1\) 可以互换,所以钦定 \(A \le B\) 后就没问题了。
考虑先把初始 \(\ge A\) 的极长 \(0\) 连续段改成 \(1\)。那么若还不存在 \(\ge B\) 的极长 \(1\) 连续段就寄了。否则这个连续段一定能往左右扩展,直到整个串变成全 \(1\)。然后再改成全 \(0\) 即可。
于是问题变为,算 \(\ge A\) 的 \(0\) 段替换成 \(1\) 后,存在 \(\ge B\) 的 \(1\) 段的串的个数。考虑容斥,算不存在 \(\ge B\) 的 \(1\) 段的串个数。那么直接 dp,设 \(f_{i, j, 0/1}\) 表示第 \(i\) 个数是 \(0/1\),当前把 \(\ge A\) 的 \(0\) 段改成 \(1\) 后 \(1\) 段的长度为 \(j\) 的方案数。转移考虑枚举下一个极长 \(0/1\) 连续段长度即可。容易前缀和优化做到 \(O(n^2)\)。
204. [ARC142F] Paired Wizards
题解的一句话很有道理:如果条件性质不多,可以用分类讨论创造性质。
首先考虑只有一个法师,设他在第 \(a_i\) 次操作攻击,那么贡献为 \(\sum a_i - i\)。设 \(s\) 为 \(a_i\) 的和,\(c\) 为攻击的次数,那么贡献为 \(s - \frac{c(c + 1)}{2}\)。
两个法师启发我们分类讨论。考虑按照 \(a_i, b_i, c_i, d_i\) 的相等关系进行讨论。可以被分成 \(5\) 类:
- \(X, Y\) 不固定且不同;
- \(X, Y\) 不固定且相同;
- \(X\) 固定,\(Y\) 不固定;
- \(X\) 不固定,\(Y\) 固定;
- \(X, Y\) 都固定。
首先 \(5\) 对 \(s_X, s_Y, c_X, c_Y\) 的贡献是固定的,计算后可以直接删去。
考虑 \(3, 4\) 中 \(X, Y\) 是独立的。考虑先计算固定的一方的贡献,然后枚举不固定的一方攻击了几次。那么 \(c\) 确定了,要最大化 \(s\) 肯定是选最靠后的位置最好。
\(1\) 对 \(s\) 的贡献是固定的,枚举 \(c_X\) 即可知道 \(c_Y\)。\(2\) 也可以类似 \(3, 4\) 枚举攻击了几次计算。然后我们有了一个 \(O(n^4)\) 的做法。
看上去就很能优化。考虑预处理 \(f_i\) 表示 \(1, 2, 5\) 中 \(X\) 攻击了 \(i\) 次,\(3, 4\) 的最大贡献。同理预处理 \(g_i\)。然后枚举 \(1, 2\) 即可。
时间复杂度 \(O(n^2)\)。
205. [AGC026E] Synchronized Subsequence
最小/最大化字典序问题,除了贪心还能 dp。
考虑设 \(f_i\) 为考虑了 \([i, n]\) 对 ab 的最大串。
若把第 \(i\) 对 ab 删掉,就从 \(f_{i + 1}\) 转移。
若不删,考虑分类讨论。
- 若
a在b前,那么它们之间的a不能保留,b一定是之前遗留的所以不用管。所以 \(f_i \gets \texttt{ab} + f_k\),其中 \(k\) 为第一个ab出现在第 \(i\) 对ab后面的。 - 若
b在a前,那么它们之间的a是之前遗留的,b一定要保留。所以去除a后找到第一个前缀和(将a视为 \(-1\),b视为 \(1\))等于这个位置的位置,然后再从后面转移。
时间复杂度 \(O(n^2)\)。
206. LOJ3646 「2021 集训队互测」《关于因为与去年互测zjk撞题而不得不改题这回事》
考虑子问题怎么做。套路地按位考虑。
- 若当前位有 \(\ge k\) 个 \(1\),那么直接把这一位是 \(0\) 的删了,答案加上 \(2^k\)。
- 否则直接把这一位扔掉。
但是这个信息不能合并。考虑维护一个从大到小的队列,那么第一种操作,删掉 \(0\) 和这一位不会改变相对顺序。第二种操作相当于 pop_front \(k\) 次再重新插入。
所以我们总共需要的数的数量 \(\le (k - 1) \log V + 1\)。
现在问题变为求链的前 \(k\) 大值。考虑重链剖分,把每个区间拿出来,扔到优先队列,每次取区间最大值最大的那个区间,按照最大值的位置分裂成两半。时间复杂度大概是 \(O(qk \log^2)\) 的。
207. P7353 [2020-2021 集训队作业] Tom & Jerry
设 \((x, y)\) 是好的当且仅当圆方树 \(x \to y\) 的路径中任意两个相邻圆点在原图相邻。那么必胜的充要条件是,删掉 \(a\) 后 \(b\) 所在连通块中全部点 \(u\) 都满足 \((a, u)\) 是好的。或者存在一个点 \(x\) 满足 \(x\) 到任意点都是好的。
考虑圆方树上树形 dp 求 \(f_u\) 表示 \(u\) 是否到 \(u\) 子树内每个点都是好的,\(g_u\) 表示 \(u\) 到父亲子树内是否每个点都是好的。
询问找到 \(b\) 所在子树即可。
208. CF1867F Most Different Tree
考虑一棵树 \(T\) 使得没有任何子树和 \(T\) 同构。那么直接在 \(T\) 上面接一条链即可。
直观感受一下 \(|T|_{\min}\) 是个很小的数字。所以直接把所有 \(T\) 暴力搜出来即可。
判定要使用树哈希。
209. [AGC005F] Many Easy Problems
平凡的。
考虑拆贡献,计算每个点在哪些情况被选。
容斥,变成计算每个点在哪些情况不被选。
相当于 \(\forall (v, u) \in E\),若点全部在 \(v\) 的子树内,\(u\) 就不会被选。
所以一个 \(K\) 的答案是一个 \(\sum\limits_{i = 1}^{n - 1} a_i \binom{i}{K}\) 的形式,其中 \(a_i\) 为总共有多少棵点数 \(= i\) 的子树。
这是差卷积。NTT 即可。时间复杂度 \(O(n \log n)\)。
210. P10149 [Ynoi1999] XM66F
考虑莫队。设 \(b_i = \sum\limits_{j = 1}^{i - 1} [a_j < a_i]\)。加入右端点时答案相当于加上 \(\sum\limits_{i = l}^r [a_i = a_r] (b_r - b_i)\)。拆开后相当于只用维护 \(\sum [a_i = x] b_i\) 和 \(\sum [a_i = x]\)。然后就没了。
211. P4566 [CTSC2018] 青蕈领主
考虑这些极长区间一定形成了树形结构,不然就无解。
对于树上的一个点,设 \(f_n\) 为长度为 \(n + 1\) 的排列,所有连续区间要么长度为 \(1\) 要么包含位置 \(n + 1\) 的方案数。那么答案即为 \(\prod f_{|son_i|}\)。
问题转为计算 \(f_n\)。
若取其逆排列,那么所有连续区间要么长度为 \(1\) 要么包含最大值。
考虑由长度为 \(n - 1\) 推到长度为 \(n\)。
若原来的排列合法,那么最大值插入任意非端点位置即可。所以贡献是 \((n - 1) f_{n - 1}\)。
若原来的排列不合法,那么极长的不包含最大值的段只能有一个,因为最大值的插入只能破坏一个。考虑取极长的不包含最大值的段,设其段长为 \(i\)。那么最大值肯定是插入其中 \(i - 1\) 个空隙;把这一段视为整体,和其他 \(n - i\) 个元素构成的段也要合法。所以贡献是 \((i - 1) f_i f_{n - i}\)。
这样我们得到了递推式:\(f_i = (i - 1) f_{i - 1} + \sum\limits_{j = 2}^{n - 2} (j - 1) f_j f_{i - j}\)。
即:\(f_i = (3 - i) f_{i - 1} + \sum\limits_{j = 1}^{n - 1} (j - 1) f_j f_{i - j}\)。
也可以直接计算了。也就是考虑如下的子问题:
仍然可以 cdq 分治计算。
考虑当前在 \([l, r]\),希望计算 \([l, mid]\) 贡献到 \([mid + 1, r]\)。若 \(r - l < l\) 那么 \([1, r - l]\) 都被算出,直接用 \([1, r - l]\) 和 \([l, mid]\) 卷两遍即可;否则 \(l = 1\),\([l, mid]\) 和 \([l, mid]\) 卷一遍即可。
212. 2024.2.26 模拟赛 T2 摸牌(cards)
设 \(g(x) = f(x) - f(x - 1)\)。推式子可以发现即要求:
令 \(g(0) = 0\),即可得到 \(g\) 的递推式,再做一遍前缀和即可得到 \(f(x)\)。
213. CF1025G Company Acquisitions
设 \(a_i\) 为 \(i\) 接着的点,设 \(F(a_1, a_2, \ldots, a_n) = \sum\limits_{i = 1}^n f(a_i)\)。即要求对于任意 \(x, y\),都有:
令 \(f(0) = 0\),有:
考虑 \(f\) 能满足这个条件的一个必要条件:
即 \(f(x + 1) = 2 f(x) - 1\)。递推计算即可。
214. CF1479E School Clubs
推式子过程略去。最后可以得到 \(f(x + 1) = \frac{(3n - 2x) f(x) - (2n - x) f(x - 1)}{n - x}\)。
但是没法线性预处理逆元,只能递推时维护分子和分母。设第 \(x\) 项的分子为 \(f(x)\),分母为 \(g(x)\)。有:
\(O(n)\) 计算即可通过。
215. 2024.2.27 模拟赛 T1 数组(array)
考虑每个点开个 vector 维护所有涉及它的 merge 操作。get \(1\) 操作是没用的,将它从 \(S\) 中删去即可;对于 get \(0\) 操作,我们把这个点的 vector 内的所有操作染黑,然后再递归地把其他 vector 中的操作染黑(我们知道一个点在某个时刻是 \(0\),它之前一定都是 \(0\))。
再套一个线段树上二分做 query 即可。
注意一下 merge 全是 \(0\) 的情况,对应到就是一个操作在所有 vector 底下都是黑色的操作。判一下即可。
216. 2024.2.27 模拟赛 T2 串串(string)
考虑建自动机。具体地,发现所有长度 \(\ge 5\) 的串都能消成长度 \(\le 4\) 的串。所以我们只用对长度 \(\le 4\) 的串且不能消成长度更小的串建点。
打个表可以知道每个串能否消成长度更小的串,以及加上一个 \(0\) 或 \(1\) 后转移到哪个点。处理询问就套个矩阵快速幂即可。
注意要把初始串消成长度 \(\le 4\) 的串。可以直接在自动机上跳。
217. [ARC172D] Distance Ranking
看似人类智慧,实则有迹可循?
考虑若要求距离全相等,直接让对角线全是 \(1\) 即可。
若要求严格小于,可以加上一些微小的偏移量。对于第 \(i\) 远的 \((A_i, B_i)\),可以设 \(p_{A_i, B_i}\) 是一个 \(i\) 越大这个值就越小的数。最后给每个数乘上 \(10^8\) 保证所有值都是整数。然后就做完了。
218. 2024.2.28 模拟赛 T2 虚树(tree)
考虑贪心,让至少两个存在于不同子树的颜色最多。
自底向上贪心,贪心过程中维护当前子树的颜色种类数的最大值即可计算。
219. 2024.2.28 模拟赛 T3 下落的数字(fall)
考虑链的部分分,线段树上二分即可。
考虑菊花的部分分,开一个 \([2, n]\) 的 set 即可。
现在我们想把这两个做法拼起来。显然能走到某个点的值一定是一段区间。
发现有个东西叫重链剖分。对于每个重链,维护一棵存区间交的线段树;再对每个点维护存所有儿子的 set。这样跳的过程就形如跳到重链上的一个点(可以线段树上二分出这个点),然后再跳到它一个非重链上的儿子。求这个直接对对应的 set lower_bound 一下即可。
所以时间复杂度是 \(O(n \log^2 n)\)。
220. CF1844H Multiple of Three Cycles
首先环是不用管的,只用判环长是否为 \(3\) 的倍数即可。
考虑设 \(f(x, y, z)\) 表示 \(x\) 个 \(1\) 链,\(y\) 个 \(2\) 链,\(z\) 个 \(0\) 链,组成所有环长都为 \(3\) 的倍数的方案数。
注意到 \(f(x, y, z) = (x + y + z) f(x, y, z - 1)\)(可以接到剩下的任意一条链,或者直接成环)。所以 \(f(x, y, z) = \frac{(x + y + z)!}{(x + y)!} f(x, y, 0)\)。所以可以直接把 \(z\) 忽略,最后答案乘一个东西即可。
所以重新设 \(f(x, y)\) 表示 \(x\) 个 \(1\) 链,\(y\) 个 \(2\) 链的方案数。考虑钦定选择包含编号最小的 \(1\) 链,它可以和另外一个 \(1\) 链拼成一个 \(2\) 链,或者和 \(2\) 链拼成一个 \(0\) 链。所以有:
对称的,考虑包含编号最小的 \(2\) 链,有:
注意到 \(f(x, y), f(x - 1, y - 1), f(x - 2, y + 1), f(x + 1, y - 2)\) 知二推二,所以若维护 \(f(x, y)\) 和 \(f(x + 1, y + 1)\),我们可以从 \((x, y)\) 推到 \((x + 2, y - 1)\),或推到 \((x - 1, y + 2)\)。
考虑倒序操作。对于一次操作,可能会让 \(x, y\) 都 \(+1\),可能让其中一个 \(+2\),另一个 \(-1\)。这些都能通过已有的两个操作凑出来。
可能初始的 \((x, y)\) 不是 \((0, 0)\)。注意到初始的 \(x, y\) 一定满足 \(x \equiv y \pmod 3\),所以先推到 \(\min(x, y)\),再对其中一个不断 \(+3\) 推到它对应的那个值即可。
221. [AGC060E] Number of Cycles
讲个笑话,一年前做过,今天模拟赛出了,但是完全不记得,然后想了一种完全不同的方法,我真抽象。
首先考虑什么时候有解。显然 \(m = n + f(a)\) 的时候有解,令 \(b_i = i, c_i = a_i\) 即可。然后考虑任意交换一对 \((i, j)\),此时 \((b_i, b_j), (c_i, c_j)\) 都会被交换。所以 \(f(b), f(c)\) 的变化量均为 \(\pm 1\)。所以 \(f(b) + f(c)\) 的奇偶性确定,若 \(m\) 和 \(n + f(a)\) 的奇偶性不同就无解。
然后发现 \(m \le n + f(a)\) 时才可能有解。考虑 \(b_i = i, c_i = a_i\) 的情形,显然交换任意一对后 \(f(b)\) 都会 \(-1\),所以交换后一定不优。
然后发现这两个条件是充要条件,下面考虑构造性证明。
先构造出 \(f(b) + f(c) = n + f(a)\) 的方案,也就是 \(b_i = i, c_i = a_i\)。考虑先从 \(c\) 入手,以任意顺序扫 \(c\) 的连通块,并且与上一个连通块合并,也就是任意交换这个连通块和上一个连通块的一对元素即可。显然它们在 \(b\) 中属于的连通块也不同。所以 \(f(b), f(c)\) 经过这样的一次操作后都会 \(-1\),所以 \(f(b) + f(c)\) 经过这样一次操作后会 \(-2\)。
扫完之后 \(f(c) = 1\),但是 \(f(b)\) 可能 \(> 1\)。我们希望当 \(f(b) > 2\) 时让 \(f(b)\) 减小 \(2\),同时保持 \(f(c) = 1\)。
不妨考虑找到一个 \(i\) 使得 \((i, c_i)\) 在 \(b\) 中不在同一个连通块(容易发现一定能找到,因为不能找到就说明 \(f(b) = 1\),可以直接退出)。此时可以直接交换 \((i, c_i)\),这样 \(f(b)\) 会 \(-1\),但是 \(f(c)\) 会 \(+1\)。
我们发现一个非常好的事情,就是 \(c_i\) 在 \(c\) 中变成了一个自环,同时所有其他的点组成了一个环。也就是说我们让 \(c_i\) 和任意一个其他点交换,\(f(c)\) 都会变回 \(1\)。那么就让 \(c_i\) 和任意一个在 \(b\) 中和它不在同一个连通块的点 \(j\) 交换,这样 \(f(b)\) 会 \(-1\)。
所以经过上面的过程,\(f(b) + f(c)\) 会 \(-2\)。
考虑快速维护这个构造的过程。可以使用一个类似栈的东西维护全部 \((i, c_i)\) 可能在 \(b\) 中在同一个连通块的点 \(i\)。找的时候直接取栈顶,在一个连通块就弹出。交换一对 \((i, j)\) 就把 \(i, j\) 都加入栈即可。
然后对一个点 \(x\) 找在 \(b\) 中和它不在一个连通块的任意一个点,可以维护任意两个连通块的祖先,其中必然有一个不是 \(x\) 的祖先。
所以时间复杂度就是 \(O(n \log n)\),\(\log n\) 是并查集复杂度,可以粗略地看成线性。实际跑得很快。

浙公网安备 33010602011771号