大一下的训练计划
「日常」CF *2400 ~ *2700 泛做,AT *2300 ~ *2700 泛做,交互题泛做。
「日常」参加 CF / AT / 牛客 ... 线上赛。
「周常」vp 邀请赛 / 省赛 / CCPC(备战可能到来的 CCPC Final)。
「长期」重构 OI+ACM 笔记。
「长期」学习 C++ 进阶语法,学习 python。
第三周(2025.03.10 ~ 2025.03.16)
星期一
CF 1253F(*2500)
若所有节点均为充电桩,则从 \(a\) 走到 \(b\) 的答案,即为 \(a, b\) 之间所有简单路径上最大边权的最小值。此时只需求出最小生成树,使用树上倍增求出 \(a, b\) 之间的最大边权即可。
记 \(\mathrm{dist}_u\) 表示 \(u\) 距离最近充电桩的距离,可以用多源点 dijkstra+heap 求出。
但正常情况下可能要经过非充电桩的节点。考虑一个贪心策略:每次走到一个节点的时候,都去距离它最近的一个充电桩补满电量再回来。
(因为走回充电桩至少需要花费 \(\mathrm{dist}_u\)。若此时电量小于 \(\mathrm{dist}_u\) 则走不回去,若此时电量大于等于 \(\mathrm{dist}_u\),则可以先花费 \(\mathrm{dist}_u\) 的电量走回去补满电量再回来,可以认为在 \(u\) 点时的电量为 \(c - \mathrm{dist}_u\))
由于起点与终点均为充电桩,则若要经过原图上的一条边 \((x, y, z)\),电池容量至少为 \(\mathrm{dist}_x + z + \mathrm{dist}_y\)(因为至少要从充电桩走到其中一个端点,经过这条边,再从另外一个端点走到充电桩)。
故对于每条边 \((x, y, z)\),使用 \(\mathrm{dist}_x + z + \mathrm{dist}_y\) 代替它的边权。此时从 \(a\) 走到 \(b\) 的答案,即为 \(a, b\) 之间所有简单路径上最大边权的最小值。
CF 1188C(*2500)
考虑先求出美丽值的上界,显然为 \(\frac{\max a_i}{k - 1}\)。
考虑对每个美丽值 \(v\),计算有多少长度为 \(k\) 的子序列的美丽值为 \(v\),记作 \(\mathrm{Count}(v)\)。但发现直接做不太好做,于是我们考虑计算有多少个长度为 \(k\) 的子序列的美丽值 \(\geq v\),记作 \(\mathrm{Count}(\geq v)\)。最后再使用 \(\mathrm{Count}(\geq v) - \mathrm{Count}(\geq v+1)\) 得到 \(\mathrm{Count}(v)\)。
(直接使用 \(\sum v \cdot \mathrm{Count}(v) = \sum_{v = 1}\mathrm{Count}(\geq v)\) 亦可)
将序列 \(a\) 从小到大排序。对于每个 \(v\),记 \(f(i, j)\) 表示考虑到了 \(a_1, \cdots, a_i\),子序列的最后一个数为 \(a_i\),包含 \(j\) 个数,且美丽值 \(\geq v\) 的子序列个数。显然有
该式子显然可以用前缀和 + 双指针优化。
时间复杂度 \(\mathcal{O}\left(nk \cdot \frac{\max a_i}{k}\right) = \mathcal{O}(n\max a_i)\)。1e8 过 5s 还是绰绰有余的。
CF 813F(*2500)
评分虚高 ...
离线加边、删边,很容易想到线段树分治。此题刚好可以回顾一下,使用扩展域并查集实现二分图判定。
扩展域并查集中的节点 \(x\) 表示 "节点 \(x\) 在二分图左部" 这一事件,节点 \(x + n\) 表示 "节点 \(x\) 在二分图右部" 这一事件。若并查集中的两个节点联通,则表示两个节点代表的事件,要么同时发生要么同时不发生。
对于原图中的每一条边 \((x, y)\),在并查集中连接 \((x, y + n)\) 以及 \((x + n, y)\)。
当存在一个节点 \(x\),满足 \(x\) 与 \(x + n\) 联通时,显然 \(x\) 不可能即在左部又在右部,故此时这张图不是二分图。
另一种理解方式:众所周知,一张图为二分图当且仅当该图存在奇环。
在扩展域并查集上,若一条路径长度为奇数,则起点与终点在异侧。故一张图存在奇环,当且仅当存在一个节点 \(x\),满足 \(x\) 与 \(x + n\) 联通。
注意,可撤销并查集使用的是按秩合并,按秩合并不能与路径压缩混用。
CF 1209E2(*2500)
首先,真正有效的列,一定在列最大值前 \(n\) 大的那些列之中。容易使用反证法证明。
考虑一列一列处理,在每一列中钦定有哪些位置为对应行的最大值。由于此题要求的是最大值之和的最大值,故在统计答案的过程中,我们不必保证每次钦定的最大值一定是真实的最大值。因为这样肯定不优。
设 \(f(j, S)\) 表示考虑到了前 \(j\) 列,其中每行的最大值确定状态为一个二进制数 \(S\)(若 \(S\) 的第 \(i\) 位为 \(1\),则表示第 \(i\) 行的最大值已经确定),则有
其中 \(\mathrm{value}(j, S)\) 表示第 \(j\) 列中,所有行号属于 \(S\) 的位置,在 \(0 \sim n - 1\) 次循环移位下的元素之和的最大值。
时间复杂度 \(\mathcal{O}(n3^n + n^22^n)\)。
CF 1527E(*2500)
评分虚高 ...
显然可以写一个很暴力的 dp。设 \(f(i, j)\) 表示考虑到了前 \(i\) 项,划分了 \(j\) 段时的最小代价,则有
直接做的时间复杂度 \(\mathcal{O}(n^2k)\) 的。
盲猜该 dp 具有决策单调性。此类代价 \(\mathrm{cost}(l, r)\) 难以计算的决策单调性优化问题,则可以考虑分治。使用类似莫队的方法处理 \(\mathrm{cost}(l, r)\)。
时间复杂度 \(\mathcal{O}(nk \log n)\)。