task18
[TOC]
1. NOI2024 - 树形图 [K] ✔️
题面
给定一张
按照如下方式给所有点分类:
- 一个点
是一类点当且仅当其是 的根 - 一个点
是二类点当且仅当其不是一类点,且存在一种删除一些图中有向边的方案得到一个新图 ,使得是 的根的点都是 的根,并且 是 的根 - 其余点均为三类点
请你求出
特殊性质 A:不存在一类点
特殊性质 B:不存在二类点
特殊性质 C:保证
存在 A、BC、B、C 的部分分
题解
Sol
首先,如果图中不存在一类点,那么是容易做的,二类点即为能到其他所有点的点
接下来我们观察一下结构:以一个一类点为根后,一定有唯一的一棵外向生成树,并且这棵生成树上只有祖孙回边
此时求解其他点是否是一类点就比较容易了,判定一个点
- 一个一类点子树向外一定有恰好一条回边,否则
会有两条路径 - 如果恰好有一条回边,设这条回边指向了
,那么 是一类点当且仅当 是一类点
那么我们就解决了已知一个一类点时,其他点是否是一类点的判定问题
接下来考虑解决二类点的判定问题,我们还是以一个一类点为根。
我们现在要将这个图删成一个子图,而原来一类点还要是一类点,因此所有树边都不能删除,且对每个一类点
那么判断一个点
- 如果有两条不能删的回边跨过了这个点,或者没有回边跨过这个点,那么一定倒闭了
- 否则我们需要在跨过这个点的回边中选择一条,使得这条回边指向的点为一类点或二类点,这个也是容易处理的,用一些支持树上链覆盖的数据结构维护即可
那么现在唯一剩下的问题就是找到一个一类点
注意到以一类点为根之后,只有回边,那么叶子一定入度为
这启发我们进行这样的过程:每次选择一个入度为
如果一个点没有被删除,那么原来它是一类点,进行一次操作后它应该仍是一度点,如果删成只剩一个点,那么我们可以将操作序列倒过来,生成出来的树就是符合条件的树,因此其一定是一类点
而如果删到最后剩
那么我们只要维护这个过程即可。
使用启发式合并,维护每个点的入边和出边,将一度点
时间复杂度
2. AGC028F2 - Reachable Cells [K] ✔️
题面
给定一个 123456789# 组成的 # 格子开始,每次向下或向右走到一个非 # 格子
求所有格子有序对 #,
题解
Sol
这题好像能被
我们可以观察到一个性质:对于一个格子
有了这个我们就可以比较容易地做到
考虑分治,如果我们当前得到的矩阵大小为
注意到如果我们枚举上半部分的格子,那么其能到达的第
进一步地,如果我们对上半部分的一行
因此,我们可以考虑动态维护一个第
- 在
最右边加入一个格子 - 删除
最左边的格子 - 查询
中的格子能到的下半部分的并集大小
接下来我们考虑如何维护这件事情。
我们维护
那么我们加入一个格子的时候就需要考虑有哪些点的

如果我们令
而容易发现我们用一个单调栈维护后缀最大值,这就是被
那么我们现在就是要对于一对
称
考虑如果处理出来
但是这样我们还是不好
因此我们只要处理出
对于一个
处理
而处理
那么我们一层的复杂度就是
3. AGC028E - High Elements [E] ⭐
题面
给定一个
额外地,我们将每个元素属于
题解
Sol
首先获取一些关于这个题的直觉。
注意到如果
而如果
进一步地,我们考虑每个前缀最大值属于哪个子序列:

可以发现,我们确定了每个前缀最大值属于哪个子序列之后,在相邻的两个红色前缀最大值之间,我们可以任选一个递增序列作为红色序列的前缀最大值,剩下的部分都可以用绿色的前缀最大值挡掉
因此如果我们考察红减绿的值,初始是红色前缀最大值减去绿色前缀最大值数量,每个红色区域可以让这个值
而不难发现我们一定只会选择红色区域或者绿色区域中的一个,因为同时加减正数没有意义,不妨假设我们选择了红色的
那么初始假设所有前缀最大值都是绿色,然后我们需要选择一个红色上升序列,每选到一个非前缀最大值会
而我们发现如果
那么我们就可以用树状数组上查询即可判断是否有解,求字典序最小只要把树状数组倒着撤销判断即可,总复杂度
4. AGC030F - Permutation and Minimum [E]
题面
给定一个长为
定义
题解
Sol
将已经配对好的
画到数轴上就是
令
转移需要注意的点:当未填好的数作为更小的数时,如果匹配了一个填好的数,那么我们是关心它匹配了哪个填好的数的,所以可以在转移的时候提前选定这个数之后会和填好的数匹配还是未填好的数匹配
复杂度
5. AGC030E - Less than 3 [E]
题面
给定两个长为
每次你可以反转
求
题解
Sol

在 10 之间画一条蓝线,在 01 之间画一条红线
每次操作后需要保证相邻两条线距离依然为
枚举一下原来的线和新的线的对应关系即可,只有
总复杂度
6. QOJ6011 - Map Reduce [E] ⭐
题面
给定一个
#:这个格子为一个障碍,无法经过,保证最外圈都是#.:这个格子为空地,可以经过S:这个格子为起点,其余和空地相同,保证恰有一个SF:这个格子为终点,其余和空地相同,保证恰有一个F
保证所有 .SF 四联通,且保证任意 2x2 不会为以下两种之一:
1 | #. .# |
(同样地,上图中 . 任意替换为 SF 后的结构也不能出现)
给定一个常数 # 改为 .,使得新图依然满足上述所有性质,并且 S 到 F 的最短路为
题解
Sol
显然
那么我们考虑按某种顺序删除障碍,使得每删一个障碍任意一对空地之间的最短路减少不超过
这是可以做到的,我们必定能找到以下两种情况的障碍之一,使得其删除后仍然合法:
1 | ... ??? |
用队列维护所有可以删除的字符,可以做到
求出顺序后我们在这个序列上二分,对比中点的最短路和
复杂度
7. QOJ9698 - Twenty-Two [E] ✔️
题面
给定一个长为
- 给定
,对每个 执行 - 给定
,对每个 执行
有
题解
Sol
看起来无从下手。
注意到
因此不难发现我们的
那么我们现在就只有
转移就是选择
转移的时候再做一个 dp 即可做到复杂度
内层 dp 的转移应当是
有两种手段优化到
Sol1
我们内层 dp 需要在所有被覆盖的位置之间转移,而我们固定
那么我们倒着扫描所有新被覆盖的位置,扫到
因此每次复杂度是
Sol2
考虑容斥,改成钦定转移路径上一些点必须是未被覆盖的位置,剩下的点随意
那么现在我们就是在未被覆盖的位置之间转移,每次后缀覆盖操作对转移的影响很小,只是舍弃掉最后几个状态,再加上最多一个状态,因此我们可以
总复杂度为
8. QOJ9222 - Price Combo [E]
题面
有
这两个商店都推出了优惠政策:你可以在同一个商店打包购买两个物品,你只需要支付这两个物品价格的
你需要在合适的商店购买每个物品,使得总花费最小
题解
Flamire 做法
Sol
首先注意到两个物品
因此我们以横坐标为 A,纵坐标为 B,那么一定存在一条左下到右上的折线,使得折线右下方均在 B 商店购买,左上方均在 A 商店购买
那么有了这个我们就可以设出 dp 状态,注意到我们可以通过若干个“极左上”的 B 的位置定义这条折线
我们从右上到左下转移,令

从
考虑从上到下扫描线,可以发现 A 区域的部分和高度无关,而 B 区域的部分和
- 在每次加入一个新的点
时,我们将 的物品的 B 区域值更新,这个可以打 tag - 在询问一个新点
会被更新的 dp 值时,我们对 的所有物品区间询问,询问 pushup 的时候维护出 A 区域的点带来的影响
总复杂度
另一个做法
Sol
考虑建两张数轴分别表示
初始我们所有物品都选择
那么注意到我们一定不会交换两条交叉的线,因此我们最后交换的物品一定如右图

那么我们就在被交换的物品之间 dp,令
从
复杂度
9. QOJ1876 - MIPT: Connecting People [K] ✔️
题面
有一个柱状图,第
每一列内部
现在你需要额外添加
- 对于两列
,以及一个高度 ,如果 ,那么你可以在 之间建一条边权为 的无向边,其中 为给定常数
你需要最小化柱状图任意两个格子
题解
Sol
这是一棵生成树,因此统计两两距离和我们可以拆到边上,贡献两边
考虑如果我们拿出最高的列作为我们分析的根,此时一个好的性质就是生成树不会有一条边跨过该列,也就是两边被分成了独立的问题
而进一步地,我们可以发现每个左右每个子树都占据了一个区间内的列:

因此我们就可以产生一个初步的想法:
但是直接转移也只能做到比较高的复杂度,需要进一步优化。
注意到我们没必要在列上考虑子树关系,我们可以把状态设到内部的点上
具体地,我们考虑转移
,表示区间 的列组成了一个子树,这个子树和外界相连的点在 ,表示我们只考虑 的列内在 及之下的部分的子树,包含了 区间的列 ,表示我们只考虑 的列内在 及以上的部分的子树,包含了 区间的列,注意到这个状态只用存一个区间的列,并且满足 不在 内,这是因为在根向上的部分,其一定向左或者向右一边能出子树,因此能出子树的这一边一定不会在 的状态里
具体如图:

写一个记搜,使用分步转移可以做到单次转移
10. TOIP2024 - 棲息地分配 [E] ⭐
题面
给定一张
给出构造或判断无解
题解
Flamire 做法
Sol
考虑一些极端情况:我们限制
讨论两种情况:
有连边,此时限制相当于 不能有共同的邻点 没有连边,此时限制相当于 最多只有一个共同的邻点
而无解的必要条件即为对于任意一对
找出度数最小的节点
:取 和任意一个没有连边的点,显然有解 :取 和任意一个没有连边的点,显然有解 :与 相连的两个点之间必须有一条连边,因此这三个点就使用了三条边,而不与 相连的点至少要有两个点和 的出边集合重复,因此边数至少为 ,不合法 :与 相连的三个点之间必须有两条连边,因此这四个点就使用了五条边,而不与 相连的点至少要有两个点和 的出边集合重复,因此边数至少为 ,不合法 :边数 ,不合法
因此根据上面的分析,至少存在一个点
由于
题解做法
Sol
图不联通显然有解。
图联通,拉出任意一棵生成树,我们合理划分集合,使得最后所有集合之间的边都是树边,如果这个可以达成那么显然合法
只要把非树边连接的端点 merge 起来即可,最多
11. QOJ9357 - Aho-Parasick [E] ✔️
题面
给定两棵
- 对
建 AC 自动机,得到 trie 树 ,fail 树 ,存在一个点集上的映射 ,使得 中有边 当且仅当 中有边 , 中有边 当且仅当 中有边 中所有字符串长度之和
数据保证有解,你可以使用的字符集足够大。
题解
Sol
这个看起来性质就不是很好,所以我们最后大概率是要缩小一下解的空间,然后直接 check。
考虑对于一个固定的根我们是否能判断合法,可以发现这是可行的,我们只要用并查集合并一下必须相等的字符,这个可以用倍增上并查集实现,建出等价关系后,我们一定是希望等价关系不同的数尽可能不同才好,因为我们希望避免出现一些额外相等的后缀
合并出等价关系之后再建出 trie 树判一下 fail 是否真的相等即可,一次 check 复杂度
接下来考虑如何缩减需要判的根的数量,注意到根的儿子的 fail 一定指向根,这个非常优美。
找出
如果存在一个度数
的点 ,那么可以发现 必须是根,否则 的儿子必定会有相同字符,因此只要判一个点即可 否则,这张图一定是一条链,这条链上的字符一定形如
aaaaaaabbbbbb,以根为分界:如果 trie 直接是这条链,直接取端点作为根即可,容易构造
否则,找到任意一条从重叠链通过 trie 边连出的点
,这个点代表的串最后一定形如 aaaaaax的形式,因此一定存在一个这样的点最后的 fail 指回链上,找到一个这样的点,设其连回链上的点为 ,可以发现 其他连出的 fail 边一定不在链上,这条边是唯一的 找到这样的一条边之后,
代表的串要么是空串,要么单个字符是 x,因此我们只要判两个点即可
因此最后我们只需要判断
12. QOJ6111 - Two Paths [E]
题面
给定一棵
题解
Sol
直接硬维护不太干净,考虑进行一些分析。
相当于我们要在
当断掉的边是确定的时候,我们直接合并直径维护即可
我们选出任意一条带权直径
路径不经过直径:此时可以发现至少有 和 中的一个路径走到了直径上去找最远点,这个可以简单地调整说明 路径经过直径: - 如果断掉的边不在直径上,设
没有和直径连通,那么 一定走到直径上取找最远点,也可以容易发现这是不劣的 - 如果断掉的边在直径上,我们特殊处理
- 如果断掉的边不在直径上,设
因此我们现在所有要处理的情况都可以转化为
- 如果
不经过直径带权中点,设 更靠近直径中点,那么不难发现 一定跨过直径中点找最远点
因此最后我们需要处理的情况就只有
此时问题就好做了,我们只要在这条链上 dfs,可以发现以每条边断开的贡献就可以表示成一个一次函数的形式,而随着我们越来越向下,有一个维度是有单调性的,因此我们的凸包可以用单调栈维护,每次询问就是在凸包上面二分
因此总复杂度为
13. NOI2025 - 数字树 [K]
题面
给定一棵
初始叶子上都没有数字,接下来有
每次操作后,你需要对
保证每次至少存在一个合法的 dfs 序
题解
Sol
可以观察到答案是
那么所有可能的操作就是翻转一个子树管理的区间,将其在最终 dfs 序中 reverse
注意到我们 reverse 一个子树实际上影响的是子树中所有出现奇数次的数,因为偶数次一定会在内部先合并完,上面翻转并没有影响
手模一下,可以猜测同一类的子树必须翻转偶数次,事实上这也是正确的(排除掉子树内只有
因此第
那么此时问题就变为了如何维护。
我们将每个子树看成一个长为
这个问题看起来很熟悉,我们可以直接将所有串按照字典序之后求相邻两个串的 lcp,因此我们能够询问串的哈希值即可,而这可以用线段树合并达成
搭配上线段树二分求 lcp,最后的复杂度是
存在做到单 log 的做法,将线段树长度开到
14. NOI2025 - 绝对防御 [K]
题面
有 0 或 1 中的一种,牌的种类已经给定,初始你会取走前
你会进行如下游戏:
- 每一回合开始,取走最靠前的两张还未取走的牌,加入你的手牌中,如果不足两张则全部取走
- 你需要选择手牌中一张
0和一张1打出,获得发动技能,发动技能后需要选择两张0打出
技能隔三个回合才能发动一次,即如果
到牌堆被取空的回合为止,如果你都合法地进行了出牌,那么你获得胜利
0 变为 1 或 1 变为 0),求最小的
题解
Sol
赛后听说这题是差分约束,于是自己搓了一个。
后来发现还是写麻烦了,所以搬运一下 wmh 老师的题解。
令
假设固定
为了方便,设我们的下标依然是 0,1,设
设 0 数,1 数
那么我们可以列出需要满足的几个条件即为:
不能发动负数次技能:
每一时刻
0的数量足够:- 每一时刻
1的数量足够: - 技能冷却:
按照差分约束的方式连边之后,我们只需要判断这张图上是否存在负环
可以发现,负环的形式相当局限,只需要要求如下事情:
- 从
走一条边到 ,然后再走链回 : - 从
走链到 ,然后再走一条边回 : - 从
走一条边到 ,然后再走链从 到 ,最后再走一条边回 : - 从
走一条边到 ,然后再走链从 到 ,最后再走一条边回 :
此时容易做到
并且这个做法也很容易扩展,可以发现同奇偶的
注意到当
时, ,下面两个可以简化为:
此时二分一个
事实上,套上一个线段树二分即可做到单 log,复杂度
15. UNR9 - 欢迎来到最前线 [E] ⭐
题面
给定两个长为
你需要选出
请对每个
题解
Sol
画到数轴上,为了思考起来方便我们假设没有相等的数,这和原问题是等难的,因为我们可以加减 eps
考虑匹配在数轴上的形态,可以发现如果有一对匹配
因此最后匹配的形态形如数轴上有一些连续区间,每段区间内的
注意到内部匹配上了可以变成括号匹配一样的形式,此时设
因此我们只需要对每一层,设其有
复杂度
16. CF2084H - Turtle and Nediam 2 [E]
题面
给定一个长为 01 串
- 设当前长度为
,选择一个 ,设 为 的中位数,删除 的最小的
求能得到多少种本质不同的串,对
题解
Sol
按连续段考虑这个串,设当前一共有
- 如果
,那么可以将 减 - 如果
,那么可以将 删除, 和 (如果存在)合并
进一步地,如果存在四个相邻的段
再注意到最后一段永远不会消失,也不会变得比原来更长
接下来考虑判断一个串
一个大致想法是我们依次匹配每一个段,假设当前匹配到了
,并且在匹配的是 ,且这两个段是同字符的 此时如果
,那么我们一定是用 去匹配 ,因为下一次匹配之前的偶数个段都可以被删掉,直接令 和 都加一即可 否则我们需要延长当前段,或者转而使用后面的某个段,对于一个
,如果我们使用它去匹配 ,那么需要吞掉 之前的所有段给 延长,找到这个的最小值即可 特殊处理结尾:结尾必须是最后一段
,并且长度不会变长,这意味着我们要匹配最后一段的时候需要跳过前面的所有东西 特殊处理开头:
- 如果开头字符相等,可以发现我们必须使用
去匹配 ,因为此时如果匹配 的话,不存在一个前面的段帮我们把 吞掉,最后的结果就是我们为了将前面干掉必定会将 消成 ,这就不如一开始匹配 ,因此 的时候我们一定使用 匹配 - 如果开头字符不等,手模可以发现我们要匹配
必须将前 段删成长度为 的,才能把字符不相等的干掉
- 如果开头字符相等,可以发现我们必须使用
那么开始列出 dp,令
如果
: 下一步可以从 转移过来,或者令当前的 直接 ,然后从 开始匹配下一段,即从 转移 如果
: 由于我们的状态只到
,我们需要想办法快速处理上面的所有转移,但是这个找到最小的 会非常难搞 考虑如下方案:
我们维护一个指针
,初始为 , 开始不断向上枚举 的长度,那么每次 , 就需要 ,多吃掉两个段来弥补长度,这时候我们如果发现 ,那么我们可以直接用 来接管之后的匹配过程,也就是从 转移过来,前面的就是一个区间和 因此我们预处理
, 表示最小的 使得 ,转移的时候先用 算掉前面的贡献,然后从 转移过来 注意
时我们必须一直使用前面的贡献,即使 存在,因为“特殊处理开头”中开头字符相等的部分指出我们第一段必须用第一段匹配 在过程中和
相等的时候我们可以直接跳到匹配最后一段,这个是上面“特殊处理结尾”部分,这个可以通过给每个 加上 达成
最后答案是
总复杂度
17. CF2124H - Longest Good Subsequence [E] ✔️
题面
定义一个序列
- 对于任意
, - 存在一个
的排列 使得对于任意 , 是满足 的最小正整数
给定一个长为
题解
Sol
不难发现一个序列是好的当且仅当所有
那么考虑 dp 来算这个事情,任意一个满足条件的序列都可以切成若干段,每一段
但是这依然不好计算,因为如果我们要区间 dp 的话,需要记录
注意到划分出来的每一个段中,第一个选择的位置一定满足
因此我们可以设出 dp 状态:设
转移的时候考虑把状态按照上面的方式切段:
没有选入子序列中: - 整个序列只有一段,即
的 覆盖了整个区间:如果 则进行 - 序列有
段,枚举包含 的段的开头在哪里,设其为 ,那么需要满足 且 ,若满足则进行
只有第三种转移复杂度为
由于
总复杂度
18. CF1969F - Card Pairing [E]
题面
给定
有
- 选择手牌中任意两张打出,如果它们相等则你的得分
- 如果牌堆非空,则抽取牌堆中接下来的两张牌加入手牌
问将手牌和牌堆都打空的时候最多获得多少分数
题解
Sol
一个非常符合直觉的结论:当手牌中存在相同的时,随便丢掉一对相等的都是最优的
那么可以发现决策不固定的只有手里恰好是
因此我们可以设状态
转移的时候依次枚举
这个是容易做到
总复杂度
19. CF2124I - Lexicographic Partition [E]
题面
对于长为
- 将
切分为若干非空段 ,生成一个新序列 为每个 中的最小值的拼接 - 字典序最大的
的长度即为 的值
现在给定长为
给出构造或者判断无解
题解
Sol
考虑如何求一个序列的
可以发现
我们的路径每一步从值的大小来看一定是上升或者下降,其中下降无论后面加什么都不会改变,而上升若后面还没有小于它的数,还是可能改变的
而我们在末尾加一个数,要么是直接加入到路径后面,要么是原来路径上某一个位置
因此我们是可以通过
而如果发生了第二种事件,我们就要求它的前驱下一步必须要走上升,因此我们这样扫一遍可以得到每个元素是否下一部必须走上升,任意时刻如果有连续两个走上升的就爆掉了
否则我们一定可以构造出来解,直接默认剩下的都是下降,然后将新数用链表插入到对应位置即可
复杂度
20. APIO2025 - Hack! [K] ⭐
题面
交互题。
交互库有一个
你需要在询问的
题解
Sol
设
显然我们只要求出一个
乍一看好像无从下手,但是我们仔细思考一下:如果我们想体现出一段区间内的所有
经过灵机一动,我们可以想到使用根号。具体地,设我们要表示出
但是这时有一个问题:我们还额外包含了两边各自内部产生的差
仔细分析一下可以发现直接二分的话是不会产生问题的:
- 对于形如
的区间,我们包含的恰好是 - 对于不为
的区间,一定有 ,而我们额外包含的区间长度一定 ,因此只要我们二分的时候优先走左边就不会产生问题
此时的代价大概为
注意到我们只需要找到任意一个
重新分析一下二分的正确性:
- 对于一个长为
的区间,我们额外包含的差一定都 ,而只要 ,这段区间内就必然有一个 的倍数,所以我们直接走进去也无妨
因此我们现在的代价就变为了
实际使用次数在
21. APIO2025 - Permutation Game [K]
题面
给定一张
你在和交互库玩游戏,每次你选择
你可以随时停止操作,你希望最大化
你需要:
- 计算出双方都以最优策略操作的情况下最后有多少
,称这个值为 - 和交互库玩一局游戏,不保证交互库策略最优,但是你需要让最后
的数量
你需要满足你玩游戏的时候,使用的操作数不超过
部分分:
部分分:
部分分:
部分分:
题解
Sol
排列可以表示为多干个环。
注意到如果
此时直接结束游戏即可。
因此现在需要考虑的情况就只剩下了链和环的情况
链的情况
可以发现当非自环的边数不超过
这个上界也确实是可以达到的
我们用链将一些环串在一起,这样会强制交互库产生一个自环,或者将两个环拼在一起
而对于一个
结合这两种操作容易构造到
环的情况
首先考虑一些简单的情况:
环长为 3
经过手模我们可以发现似乎只有一个偶环的时候我们无法从中创造一个自环
事实上这是正确的:我们可以证明交互库可以让奇环的数量不增:
- 如果这三个点不属于同一个环,交互库只要合并两个环,奇环的数量一定不增
- 如果这三个点属于同一个奇环,任意交换一条边必定会将这个奇环拆成一个奇环和一个偶环,奇环数量不变
- 如果这三个点属于同一个偶环,由于
是奇数,因此一定存在一条边会将这个偶环拆成两个偶环,奇环数量不变
因此答案有一个上界即为奇环数量,事实上这也是可以取到的:
- 对于一个长为
的环,我们显然可以从中造出一个自环 - 对于一个长
的奇环,我们只要操作三个相邻的点,交互库要么使环长 ,要么造出一个自环
环长为 4
经过手模可以发现大部分情况下上界为
观察到对于一个
因此我们按照如下方式操作:
- 如果存在一个
环,就操作这个 环产生一个自环 - 如果存在
环,就操作这个环产生一个自环或 环 - 否则就随便将环拼在一起
可以发现,这样操作到最后只会剩若干个大小和为
此时我们考虑直接做原题,而环长为
环长为奇数
奇环不会增加的结论依然成立。
但同时,对于过小的奇环我们同样无法操作。
具体地,如果最大的奇环加上所有偶环的大小
这种情况下我们需要献祭掉最大的一部分奇环,将它们合并到一起,直到最大的奇环加上所有偶环的大小
而注意到此时操作之后所有偶环的大小和为
因此我们可以提前计算出要献祭掉多少奇环,这就是我们的最终答案
得知答案之后构造是容易的(奇环均指未被献祭掉的奇环):
若存在奇环大小
则直接操作 当最大奇环大小不足
时,我们往上拼偶环 - 否则最大奇环大小
,采用 ,该环每步差为 或 ,交互库必定会拆出一个自环或让环长
分析一下操作步数:我们的过程可以看成,先把最大的奇环拼到
每个奇环会贡献
一开始我们还需要花不超过环数的代价造出第一个
由于奇环大小至少为
环长为偶数
答案依然是
此时我们不断给一个环
若环长为
因此可以认为我们在
这个之前我做麻烦了,所以我阅读了一下 qoj 上 bachbeo2007 的提交记录,他使用了如下的构造:

将
然后走绿线返回,一开始先跳一步
调整一下长度容易做到访问
现在我们具备了从任意
但非常不幸的是,这样会使用
我们需要把这个降到
而为此我们可以有
- 首先合并一些环造出来一个
的,把它操作掉,得到至少一个 的环,这部分最多 次操作 - 然后开始用这个
的环去合并其它的环,对于任意 ,我们都可以在三次操作内拆出一个自环将它变为 - 我们在剩下的环中再合并再造出来一个
(如果造不出来那么直接乱合即可),此时对于任意一个环 ,我们只需要用两个 不断操作,把其中一个从 变成 ,然后用 和 合并即可,我们又会得到一个新的 - 最后将其它所有环操作完之后,将这两个环操作掉
再改一下这个方案,让它对于交互库的其它策略也合理即可
22. CF2129F - Top-K Tracker [K]
题面
交互题。
交互库有一个
你需要通过询问猜出
- 操作 1:给定
个不同的下标 ,交互库会返回 中的前 大的值 - 操作 2:给定
个不同的数 ,交互库会返回 中的前 大的值 - 操作 3:给定
个不同的下标 ,交互库会返回 中的前 大的值 - 操作 4:给定
个不同的数 ,交互库会返回 中的前 大的值
设四种询问使用的次数分别为
F1:
F2:
题解
Sol
对于 F1,我们只使用操作 1 和 3,并且一操作只使用
我们一共有
这些二进制数中最多一共有
因此我们只要构造一种合法的赋值二进制数的方案即可
这是容易做到的。
对于 F2,我们需要进一步利用操作的性质,我们现在开始使用大于对应长度的操作
不妨假设我们仍然先使用
用类似的配对方式,我们依然给
因此我们分为
现在我们最后一次操作需要解决的就是,我们有
注意到
那么我们将
这时,我们每组
由于大数都大于小数,所以我们这样做会出问题当且仅当
23. UNR9 - 滑冰 [K] ✔️
题面
给定一个 #. 的字符矩阵,其中 # 为障碍,. 为空地
你初始从一个空地出发,每一步可以选定上下左右中的一个方向,你会一直移动直到撞到边界或者障碍
你需要求从哪些空地出发能存在一条路径经过所有空地(在移动中滑过也算,不需要停下)
题解
Sol
下文
做法
我们首先将格子之间的可达关系建图连边,然后缩点,我们需要走一条缩点 dag 上的路径
在这张图上,如果一个格子四个方向都不紧贴障碍,那么它就是一个入度为 0 的单点 scc,这没有什么意义,所以我们删除这样的点
此时一个格子被经过的条件是:要么它竖着走的 scc 被经过,要么它横着走的 scc 被经过
并且从一个格子起点出发就是:要么从它竖着走的 scc 出发,要么从它横着走的 scc 出发
此时我们就可以把它描述成一个 2-sat 模型了,用布尔变量表示一个点有没有被经过:
- 每个格子都必须被经过:横着的 scc 和竖着的 scc 至少要访问一个
- 走过的应该是一条路径:保证被选上的任意两个 scc
,要么 能到达 ,要么 能到达 ,这样限制出来一定存在一条路径经过所有选中的 scc - 限制起点是某个 scc:将这个 scc 设为必选,将逆拓扑序大于这个 scc 的点全设为不能选
此时对每个 scc 作为起点跑一遍 2-sat,点数为
可以通过手段实现到
及 做法
进一步观察性质。
考虑 scc 之间的连边是怎么产生的:

必然是通过这样至少一边是紧贴障碍的红色格子产生的,而这个红色格子又必须被经过,因此我们可以得到一个关键的结论:任意一条有向边的两个端点必须至少经过一个
有了这个结论,可以发现有解的图会受到非常强的约束。具体来说,我们拎出一条最长的合法解路径,称路径上的点依次为

可以发现:
- 由于
是合法路径,所以不存在形如红色的,两个端点均不在 上的边 - 由于
是最长的合法路径,所以不存在 ,或者 ,或者 的点
可以发现,这条合法路径的长度一定等于原图中最长路径长度
那么我们求出从原图中每个点出发的最长路长度
此时
上任意两个相邻的点至少要选一个 - 我们按照
为节点分层,那么对于每个 ,这样的点必须选恰好一个 - 如果我们选了一个不在
内的点 ,那么 和 层的 必选, 为了让选出的点集是一条路径,我们需要要求 的边均存在
可以发现保证这些条件后我们求出来的解就一定满足条件,一三条件是容易用
而加入判断端点可以完成的,注意到
对每个起点做一下即可做到
注意到判断
因此我们可以先花
做法
称连向
我们唯一需要优化的部分是每个
观察一下 2-sat 图的结构:这些
也就是说
这个可以直接在缩点 dag 上递推得到,容易做到线性
因此我们在
24. IOI2025 - Souvenirs [E] ⭐
题面
交互题。
有
你只知道
- 你指定一个钱数
,如果 或者 你就会原地爆炸 - 否则,会依次考虑
: - 如果
,那么你会获得一件 的物品,并且 会减少 - 否则不做任何变化
- 如果
- 最后你会得到你购买的所有物品,以及你剩余的钱数
你有足够多的钱,请合理操作使得最后你没有原地爆炸,并且恰好买了
题解
Sol
注意到
那么我们一开始先询问一次
如果只购买了
,那么我们可以直接通过剩下的钱数求出 的值,此时 就转化为了形式类似的问题 如果购买了
件物品,那么设一共用了 的钱,这其中最小的物品必定小于等于 ,那么我们以 作为界就可以将其转化为更小规模的问题 求出
的所有物品之后,我们可以再结算一遍购买的所有物品,把已知的物品都结算进剩余钱数,然后再重复这个过程
可以发现,我们每个区间
最后再重复买一个物品把次数补齐即可
25. IOI2025 - World Map [E]
题面
给定一张
各至少出现一次 - 对于任意一个四联通的方格对,上面的数组要么相同,要么在
中有连边 - 对于任意一条
中的边 ,至少存在一组四联通方格对,使得两个数字分别为
你需要保证
题解
Sol
显然图需要连通。
一种
通过一列纯色
然后我们用
注意到一个数只有第一次出现需要三列,之后出现都只需要一列,这样列数降到
斜过来放在对角线上,一个颜色用三条对角线,此时我们就不需要用
仔细思考一下,可以发现我们只需要每个节点的可用长度偏序
而
咋克优化
考虑优化一下处理边的方式:假设
1 | 1f12 |
其中
我们需要的斜线长度恰好是需要处理的点数,而这种构造中每个点额外用了一条斜线,只要我们能够合理地匹配每个点,最后得到的矩阵应该满足
找出原图的一棵 dfs 树,先按照 dfs 序遍历,得到一个长为
匹配的方式是:dfs 时,如果当前点
注意到此时会剩下一些叶子没有匹配,因此我们额外要求每一对匹配
现在我们需要给每个匹配分配在什么时候处理它们的邻边,使得斜线长度都够用
可以说明,我们在遍历完
- 前面是容易说明的,处理这对匹配时,前面必定 dfs 到过
的所有祖先,以及 子树内的所有叶子 - 后面只出现过
的所有祖先,但是由于我们叶子空余了一些叶子没有匹配上,所以我们实际上使用的斜线不超过 ,因此相当于叶子数量个空斜线放在最后,这样后面的斜线个数也是足够的
因此我们在
26. IOI2025 - Triple Peaks [E]
题面
给定一个长为
第一问:给定
第二问:给定
数据点:
题解
Sol
第一问:
分类讨论情况:
- 最大值为
,那么 已经确定, check - 最大值为
,同理 - 最大值为
,且 ,依然 check - 最大值为
,且 ,这种情况需要处理
可以通过简单的加加减减可以发现有
那么我们枚举
可以证明,这样的复杂度是
- 对于
的桶,称其大小从小到大为 , 的桶大小从小到大为 ,显然有 - 我们会从中选择
个不相同的对 ,然后贡献 - 对于
,其和所有 配对贡献不超过 ,而这样的 个数不超过 ,因此这部分复杂度不超过 - 对于
,其配对一次复杂度不超过 ,最多匹配 次,因此这部分复杂度不超过
因此我们在
比较需要注意力的做法:
在
第二问:
显然我们要造的是最后一种情况,因为只有这种情况可能出现
注意到这种情况实际上是经过
因此我们可以考虑选定若干个
我们需要让交点尽可能横坐标都不同,直接随机即可获得 ~90pts。
再加一点乱搞调整可以获得 100pts。
哦,好像直接每次去新交点最多的就可以在
27. IOI2025 - Festival [E]
题面
有
你如果当前有
你初始有
题解
Sol
不管怎么样先 exchange argument 一下。
考虑
而注意到如果过程中任意时刻我们的钱数
那么我们取物品的顺序一定是按照
考虑一下什么时候我们取物品会赚钱,即
那么我们先把赚钱的都操作掉,接下来不管我们怎么操作钱数都不会再增加了,任意操作都至少会让我们的钱数
进一步地,可以发现我们操作不了多少轮就破产了。
具体地,对于一个物品
因此直接在原序上 dp,记
最后再枚举每个状态二分一下统计
复杂度
28. IOI2025 - Obstacles for a Llama [E] ✔️
题面
给定一个长为
定义一个
部分分:对于所有询问
题解
Flamire 做法
比较麻烦。
考虑一个过程:维护两个区间
- 找到
中的最小列,用这个最小值去扩展 ,让 向两边扩展直到扩展不了为止 - 找到
中的最大行,用这个最大值去扩展 ,让 向两边扩展直到扩展不了为止
最后操作不动的时候,如果
考虑维护这个过程,注意到所有起点的行为
因此对于
而对于有
那么接下来我们
这就等价于,我们要找到长度最小的
注意到对于一个
这形成了一棵树,每次我们要找的就是
复杂度
le0n 做法
考虑割是什么样的。
经过一些手模可以发现,如果我们提前在两端分别加入全是障碍的列,任意
证明不会。
那么我们只用考虑 U 型割就能判断两个格子是否连通,求出所有 U 型割之后这个可以使用 xor-hash 实现
而两列
有效的区间只有
那么我们就解决了
而当有区间的限制的时候,相当于多加了两列障碍,因此原来不连通的现在还是不连通,而我们需要额外考虑的就是 J 型割和 L 型割,即中间某一列拐一下拐到边界上
这种也是比较容易处理的,我们提前预处理出来每一列的前缀障碍段,这上面向左向右延伸的最长长度
查询的时候只要查询
复杂度
29. IOI2025 - Migrations [K]
题面
通信题。
有一棵
考古队:
依次考虑
,考古队会收到 ,然后考古队需要结合之前收到的 ,决策是否要发送信息,其中信息是一个正整数 博物馆:
博物馆会得到每一时刻,考古队发送的信息(或者没有发送信息),博物馆需要根据这些信息返回任意一条原树上的直径的两个端点的编号
设你发送的信息整数最大值为
题解
Sol
做法
考虑直接使用最后
我们最后需要发送两个值为
但是在传递信息的过程中,
我们每次发送一个 bit 的信息,发送信息
如果没有被替换,那么我们就只需要
而如果中途有一个位置被替换了,不妨设替换的是
在传
这样我们最多会损失一位信息,总共需要
做法
改进一下上面的做法。
注意到一开始我们使用二进制发
但这样还是不够优,考虑将用作标识的数也削减到一个,这样我们就有四个数可以传信息
具体地,我们用
那么接到
上一位改
在这之后,用二进制继续传即可,其余部分和上面类似
这样总共需要
做法
注意到我们可以用一个位表示前四位是否进行了对
考虑四个位一块
但是这样有一个问题,就是
因此我们还需要最后开一位用于特判。
做法
我们需要尽可能最小化非零的位置数量,因此考虑优化一下我们的信息表示:我们把连续
那么我们用这个信息同时限定
具体地,对于一个块
- 令
,那么我们可以用这个块传递一个 的信息 - 选定
,将 分别分成 个块,然后返回块二元组的编号 - 对应地缩减
,然后将 同时加入
但是这个效果还是不够,我们可以加一点小优化:
- 第一个块我们可以让
,所以这样我们只用考虑 个块的二元组 - 每个块处理的时候我们可以先将
加入 ,然后再做处理,最后将 加入
加了这些改进之后,跑一个 dp 算出最优的分块方式,可以发现我们可以用前
接下来我们手玩一下后
在
现在我们要给每条边分配一个
为了让我们的讨论简单一点,我们希望拆出来的图都是同构的,这样我们就只用讨论一种情况
这个是很松的限制,我们限制图形如
后面的类似,但是划分更加 ,最后经过
30. 图灵杯 2025 - 棋无常树 [K]
题面
给定一个
额外有限制
现在给定一些点的
题解
Sol
在一个子树内定义“确定出现的数”,即为
可以发现,我们设状态记录子树内,除了确定出现的数之外还出现了多少种数,这个是几乎可以转移的。
问题在对于
因此我们最后的状态是:
转移
- 枚举每个儿子
: - 处理一下值为
,将 的 维转变为记录 是否存在 - 然后依次枚举每个值
,如果其在 中必然出现,但在 中不必然出现,那么对于 做一遍转移,转移其中是否包含 - 最后将
合并到 上
- 处理一下值为
- 合并完所有儿子
之后: - 若
则直接删除所有出现过 的状态 - 否则依次枚举
的每一个还未被标记为必然出现的数,进行一次转移,让它必然出现
- 若
注意到过程中只有将
而这相当于我们需要解决如下问题:
- 给定一个长为
的数组 以及一个长为 的数组 ,枚举每个 ,以及一个 ,将 贡献到 ,要求在 时间内求出
这个即为两个集合合并,去除重复元素的转移
事实上,这也是可以做到的,我们从小到大枚举
讨论一大堆细节,即可在
- Title: task18
- Author: Flamire
- Created at : 2025-07-07 00:00:00
- Updated at : 2025-08-31 19:50:58
- Link: https://flamire.github.io/2025/07/07/task18/
- License: This work is licensed under CC BY-NC-SA 4.0.