Solution Set - “一二行诗句相遇,十万颗恒星解体”
- 0.「集训队互测 2018」Fim4 ⭐
- 1.「ABC 294Ex」K-Coloring ⭐
- 2.「NOI Simu.」解码
- 3.「NOI Simu.」图 ⭐
- 4.「NOI Simu.」表达式
- 5.「ULR #1」「UOJ #577」打击复读 ⭐
- 6.「UR #7」「UOJ #84」水题走四方 ⭐
- 7.「UR #8」「UOJ #118」赴京赶考
- 8.「UR #8」「UOJ #119」决战圆锥曲线
- 9.「SDOI 2013」「洛谷 P3303」淘金
- 10.「ZJOI 2019」「洛谷 P5327」语言 ⭐
- 11.「ZJOI 2019」「洛谷 P5328」浙江省选 ⭐
- 12.「UR #8」「UOJ #120」宿命多项式 ⭐
- 13.「NOI Simu.」乐 ⭐
- 14.「NOI Simu.」铲雪 ⭐
- 15.「CF 1310C」Au Pont Rouge
0.「集训队互测 2018」Fim4 ⭐
- Link & Submission.
- 「A.分块」
暂时不知道正解, 也不知道兔写了依托啥玩意儿. (
询问串离线建出 AC 自动机, 我们需要将母串在 AC 自动机上匹配, 最后在 fail 树上求子树和得到答案. 母串长度 不算太长, 我们可能可以压位来节约一个常数级别的复杂度卡过.
取步长 , 对于 AC 自动机上的每个结点, 处理其 种转移到达的结点, 匹配时只在 步到达的结点打标记, 这样匹配过程就可以除上一个 . 此后, 我们需要对 AC 自动机上的结点释放标记, 类似搜索地实现可以做到单个结点 释放标记. 复杂度 , 主要瓶颈是前一个部分的空间, 这里取 可以卡过. 当然兔释放标记的部分写的真的是搜索, 如果把这个东西展开成循环应该会快上不少.
1.「ABC 294Ex」K-Coloring ⭐
- Link & Submission.
- 「A.数学-容斥计数」
题如其名, coloring 板题, 这个问题的一个表现较优秀的写法是采用缩图策略:
- 若图不连通, 递归求解.
- 若存在叶子, 答案乘上 , 删掉叶子及其连边, 递归求解.
- 若存在度数为 的点, 讨论其两侧结点颜色是否相等, 递归求解.
- 若上述缩图策略无效, 用子集卷积暴力求答案.
毛估复杂度, 当图无法收缩时, 每个结点的度数 , 则结点数 . 因此, 暴力部分复杂度 , 容易看出其余部分不是瓶颈, 这样就得到了一个 的算法. 当然, 通过更精细的分析, 可以得到更紧的界.
不好写? 一个 sweet 的写法是, 先判连通性, 然后取度数最小的结点, 容斥其邻接边颜色取等情况. 这种方法的递归 "底层" (无法缩图的情况) 复杂度略高 (吗?), 但的确舒服很多.
2.「NOI Simu.」解码
rep (t, 0, cur - 1) {
if (same(i, t, cur, stpn)
&& same(i, (t + 1) % 10, cur, stpn)) {
return true;
}
}
你说得对, 但 和 是第 位而不是第 位. 你真会写代码.
第一个想法是二分答案, 那就一条路走到黑吧! 对于二分的答案 , 我们考虑检查是否存在一个 使得 的前 步对应相同的字符串.
比较 key 的 observation 是, 设 在 步内产生过字符变换的最高的位为 , 则 的前 位 (第 位至第 位) 必然相同. 我们从 往上枚举 第一个不同的位以及 的对应取值, 注意取值是越小越好, 这样可以尽量避免产生 " 先进位, 再进位" 的情况, 减少对字符表的要求. 如果构造过程中已经使得 那就一定有解了 — 取 的高位和 相同即可. 贪心判定, 最终复杂度是 , 其中 .
3.「NOI Simu.」图 ⭐
- Private link & Submission.
- 「A.构造」
差不多会了, 写出来的是:
if (sum[rt] != 2 && sum[rt] != clr[rt]) {
rep (u, 1, n) if (u != rt && clr[u] == clr[rt]) {
clr[u] = 2; // Stimulate an adaptation (always exits).
for (int v = u; v != rt; v = fa[v]) {
sum[v] = 0;
for (auto [w, i]: tre[v]) if (w != fa[v]) sum[v] += ans[i];
sum[v] %= 3, ans[fe[v]] = (clr[v] - sum[v] + 3) % 3;
}
// break;
}
}
注释行没有. 乐.
先判断掉 无解, 因为题目中给了很多限制 (三部图, 连通), 我们可以坚信剩下的情况都有解. 先来考虑二分图的情况. 图上构造的常见思路: 取一个生成树, 我们就在生成树上调节度数. 假设在一种二染色方案中, 点 的颜色是 , 一个自然的想法是构造边权使得 的边权和 . 在树上, 我们可以轻松地调节好除根以外的结点, 如果此时根 非法, 怎么办呢? 注意我们只用了两种颜色, 接下来就需要引入 了. 我们取 且 , 令 , 对应调整 这条路径, 此后 必然被改变, 不管变成什么都是一定合法的!
好, 放到三部图上, 我们仍然尝试用树构造 . 与二部图不同的是, 我们需要用树外的边构造答案. 非二分图一定存在奇环, 奇环上的边交替 就可以让特定的点 , 我们用某个奇环调整根结点即可.
两部分复杂度都是 .
4.「NOI Simu.」表达式
- Private link & Submission.
- 「A.图论-2_SAT」「C.性质/结论」
这个… 有点怪啊, 猜猜出题人的 motivation 好了.
首先, 这个问题不弱于 2-SAT, 且 SAT 结构整出来的 DAG 可以等价地描述变量关系, 我们不妨就在图上思考. 所有量词都是 时, 可以导出原命题为真的必要条件:
- , 和 不再同一个 SCC 中.
需要研究的是全称量词, 我们可以枚举一下两个量词之间的位置关系:
- , 就是上面的东西.
- , 如果 , , , 任意一者的原命题或逆命题为真, 则原命题为假. 特别地, 时, 仍然有同样的约束.
- , 如果 , … 任意一者为真, 则原命题为假. 虽然初始的说法不长这样, 但经过一些化简可以得到这个结果.
- , 没有额外限制, 已经在 约束过, 确定之后, 一定存在.
最后, 我们惊讶地发现这些限制都很好判断, 甚至不需要求 DAG 可达性. 结束.
5.「ULR #1」「UOJ #577」打击复读 ⭐
6.「UR #7」「UOJ #84」水题走四方 ⭐
- Link & Submission.
- 「B.贪心」「C.性质/结论」
不管是暴力 DP 还是研究结论, 我们必然要先来约束这个超高自由度的移动操作. 可以发现, 我们可以构造方案使得其中一个人从来没有传送向另一个人, 我们把没有传送过的人叫做本体, 另一个人叫做喻体分身, 那么, 整个操作过程就是: 本体在一条树链上行走, 分身去处理所有的分支子树.
进一步的, 本体和分身的一些行动可以并行: 当分身只需要处理一条链时, 本体就不需要站在原地传送分身, 而可以继续向下走. 当然, 取子树中最长的树链一定最优, 这给本体预留了最多的行动时间. 麻烦的是, "子树最长链" 需要排除本体走的链, 我们根本不知道这条链是什么呀!
贪心不了了, 我们尝试 DP. 如果知道本体在并行行走结束时站的位置, 我们就能求出分身处理的子树, 继而得到答案. 因此, 设 表示处理好了 子树外的所有点, 现在本体和分身都站在 上时, 处理剩余部分的最短时间. 我们枚举第一次并行结束时本体走到的结点 , 则 中需要存在一个深度不小于 的点 (这样才能并行), 有转移
其中 表示 子树内叶子深度和, 表示 子树内叶子个数, 表示 的深度. 当然, 当 是 的唯一儿子时, 有非并行的转移:
那么 就是答案.
DP 优化倒是好说 — 并行转移中, 肯定只需要被最近的可转移的 更新. 我们只需要对每个点 求出这个祖先 即可. 仍然是按子树处理, 递归完子树后剩下未被求解的 组成链表, 合并时交叉更新就行. 复杂度 , 尽量不要引入递归.
7.「UR #8」「UOJ #118」赴京赶考
- Link & Submission.
横纵坐标独立, 距离是区间内连续段数量. 注意是在环而非链上行走. .
8.「UR #8」「UOJ #119」决战圆锥曲线
- Link & Submission.
圆锥曲线是断然不会算的, 我们不如找一点简单的支配对来剪枝, 例如, 若 和 满足 且 , 则 断然不可能参与答案贡献.
等等, 序列随机, 这个后缀最大值的数量是 的! 我们直接线段树维护区间最值, 然后树上遍历出所有后缀最大值更新答案即可. 复杂度 , 题目中有 .
9.「SDOI 2013」「洛谷 P3303」淘金
- Link & Submission.
- 「A.DP-数位 DP」
最暴力的暴力就是最正解的正解, 不愧是你.
显然横纵坐标独立, 设 , 我们如果求出所有的 , 剩下的工作就是求 的前 大, 这个倒好说, 拿堆随便算算就行.
怎么求 呢? 注意到 的 必然有 , 毛估不过 , 跑出来差不多 , 直接用 std::map
记忆化所有状态跑数位 DP 就行. 设状态数为 , 复杂度为 , 其中 .
10.「ZJOI 2019」「洛谷 P5327」语言 ⭐
- Link & Submission.
- 「A.树论-虚树」「A.启发式合并/分裂」
路径交叠特别复杂, 跨子树根或者跨分治中心计数都不太方便, 我们可以考虑另一种计数策略: 对于每个点, 求出其能够开展贸易的点数.
对于点 答案的求解, 我们只需要保留所有经过点 的路径, 求出所有这些路径端点构成的虚树, 虚树 (对应于原树上) 的大小就是答案. 注意答案本身之和虚树形态有关, 而这样的虚树可以通过树上差分删除/加入单点, 启发式合并点集来维护, 这道题就这样了. 复杂度 .
11.「ZJOI 2019」「洛谷 P5328」浙江省选 ⭐
- Link & Submission.
- 「A.计算几何」
注意到 很小, 所以我们的算法大抵是一层一层地大力找到能当第一的一次函数, 把它们删除, 如此迭代. 当然, 求能当第一名的函数并不复杂, 就是求这些函数构成的下凸包, 在计算几何的语境下可以说是半平面交, 不过全部是 的一次函数, 单调栈扫一扫就行.
求出凸包后由于各个位置被已经去掉的函数的覆盖次数是不一样的, 我们需要拿已经被剥离的上层函数在当前凸包上二分出覆盖部分, 打差分标记, 最后扫描凸包查看凸包上每个函数的露出部分是否存在一个整点, 该整点只被覆盖了层数 次, 如果存在这样的整点, 对应的函数就进队 (迫真) 了.
复杂度 .
12.「UR #8」「UOJ #120」宿命多项式 ⭐
-
Link & Submission.
-
「A.构造」「A.数学-组合计数」
尝试通过枚举系数来满足限制. 不妨来计数整系数降幂多项式 , 使得 , 不难发现这和原问题等价. 设
那么
设前面的部分为 , 则
可见, 我们关心 的值. 这里比较 key 的转化是, 我们可以通过预先构造 来降低信息量. 假设我们枚举了 , 令 在这种构造下,
其中
可见, 的确只需要 就能计算方案数了. 直接枚举的复杂度是 .
你妈的, 怎么还有 次询问啊?
尝试把 这层枚举去掉. 好消息是, , 因此 对 的影响是一个匀速的转圈, 总共只有 个发生取模的点, 在两个相邻取模点之间的答案贡献恒定, 这样就能做到单次 啦! 不过毕竟还得排序, 所以可以若干个序列统一进行 值域的桶排.
赞叹一下现代编译器, 编译期求值展开所有预处理过程就不说了, 对小数组的循环迭代貌似会倍增地展开成顺序结构 (比如对 int ary[7]
的迭代, 会生成迭代 次的汇编, 然后判断跳转). 但不知道为什么, 我的提交的代码在 g++ 10.3
中开启 -O3
选项时会警告:
.../main.cpp:66:38: warning: iteration 7 invokes undefined behavior [-Waggressive-loop-optimizations]
66 | rep (j, 0, k) val[k] += dpwr[k][j] * rem[j];
| ~~~~~~~~~^
.../main.cpp:5:52: note: within this loop
5 | , l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
| ^
.../main.cpp:66:5: note: in expansion of macro ‘rep’
66 | rep (j, 0, k) val[k] += dpwr[k][j] * rem[j];
| ^~~
而且相同的警告重复了三次 (难道对应了上面的倍增次数? 阅读汇编代码发现这个循环似乎确实被倍增展开了). 不知道为什么会有这个警告, 逻辑上 也不可能 啊.
13.「NOI Simu.」乐 ⭐
- Link & Submission.
- 「B.复杂度平衡」「B.std::bitset」
乐, 复杂度感知对了也除不下去 .
经过足够时间的试错之后可以发现这题不太能 (实际上, 似乎可以归约矩乘证明), 我们不得不在 的震撼规模下考虑根号分治, 继而可以猜到一个类似 的复杂度 — 我们只需要在某种块长上除掉一个 , 就可以平衡出正解.
设阈值为 , 对于询问 , 若 , 该询问最多在 种颜色的连通块中有意义, 我们可以 ( 同阶, 下同) 地查询它们.
现在, 我们只需要讨论满足 的询问. 注意这样的点只有 个, 我们称它们为关键点. 对每种颜色, 考虑其所有连通块, 若连通块大小不超过 , 我们还是可以 地大力更新答案 (一共只有 个答案是我们关心的, 可以直接保存). 否则连通块大小大于 , 这样的连通块总共只有 个, 我们给这个连通块一个新的标号, 将其记录在其中的每个关键点上. 最后查询时, 我们需要额外加入这部分贡献, 即两个关键点的标号集合的交集大小, 用 std::bitset
维护即可. 这部分的复杂度是 .
取 , 平衡得到 , 不过空间是 的, 实际实现时阈值不能太小.
14.「NOI Simu.」铲雪 ⭐
- Link & Submission.
- 「A.树论-树链剖分」
(这个星星纯粹是对代码量的反抗 w.)
一眼丁真, 鉴定为道路铺设. 边上权值道路铺设的结论很简单, 我们知道
其中 是 邻接边边权和, 是其中的最大边权, 这个式子很好理解, 难点在于维护.
当 时, 我们定义此时 的 (之一) 为 的 dominator, 记为 , 若不存在这样的点则 . 注意到若一个点 的两条邻接边同时被 , 只可能从非零值变为 , 若 只有一条邻接边被 , 才可能从 变为非零值. 也就是说, 的全局变化次数是 的. 我们可以树剖剖分, 将 非零, 且非父亲, 非重儿子的 拉到线段树上维护贡献和 的最小值, 用于检测 变化; 其他的 大力维护答案就行. 复杂度 .
15.「CF 1310C」Au Pont Rouge
- Link & Submission.
写一个 甚至 的玩意儿 ( 同阶), 全程暴力可过.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!