能否还愿。

置顶部分

前言

能否还愿。

常见错误

  • 先肉眼调试。
  • 模板写得太快了导致出错,并且查错的时候根本没有往模板上面去找。

Tricks

  • 求一个序列经过邻项对换变成单谷序列的最少操作数。

不妨只考虑大数对小数的贡献,这样便于统计。

对于一个 \(a_i\),考虑其放在“谷”的左边还是右边。这样来分类讨论的话,答案记为 \(a_i\) 左边比它小的值的个数和右边比它小的值的个数的较小值。BIT 可以简单维护。

  • 区间 LCA:

\[\displaystyle \operatorname*{LCA}_{i = l} ^ r i = \operatorname{LCA}(\operatorname*{avgmin}_{i = l} ^ r dfn_i, \operatorname*{avgmax}_{i = l} ^ r dfn_i) \]

记 \(f(i)\) 表示 \(\operatorname{LCA}(i, i + 1)\)。

\[\displaystyle \operatorname*{LCA}_{i = l} ^ r i = f({\displaystyle \operatorname*{avgmin}_{i = l} ^ {r - 1} dep_{f(i)}}) \]

To Do List

  • P16280 题解。
  • P15975。
  • P14031。
  • CF1542E。
  • CF1826E。
  • CF1774F。

进程

P9350 [JOI 2023 Final] 宣传 2 / Advertisement 2

评级:普及/提高-。

用时:\(45 \min\)。

拆绝对值,而后有两条限制,直接排序枚举即可。

P14332 [JOI2021 预选赛 R2] 活动巡游 / Event Hopping

评级:普及/提高-。

用时:\(60 \min\)。

分成在当前城镇和不在当前城镇两个部分 dp,对于后者二分转移即可。

P11663 [JOI 2025 Final] 勇者比太郎 2 / Bitaro the Brave 2

评级:普及/提高-。

用时:\(45 \min\)。

二分初始力量,check 里面写个简单的前后缀判断即可。

P7804 [JOI Open 2021] 决算报告 / Financial Report

评级:提高。

用时:\(120 \min\)。

有一个非常显而易见的转移:

\[dp_i = \max_{a_i > a_j \land j \in sub(i)} ^ {j \in [1, i - 1]} \{ dp_j + 1 \} \]

关键在于如何求 \(sub(i)\)。

我们按 \(a_i\) 排序,而后从小到大将其下标插入 std :: set。不难发现若 \(j \in sub(i)\) 当且仅当在 std :: set 中 \(i, j\) 相差不超过 \(D\)。

在此之上,线段树维护转移即可。

P11202 [JOIG 2024] 名前 / Name

评级:提高+/省选-。

用时:\(240 \min\)。

对于 \(K\) 这个条件而言,考虑逐步限制。

  • 对于 \(K = 0\):记 \(dp_{i, j}\) 表示已经考虑到 \(S_i, T_j\) 的最短长度,是一个经典的双序列 dp。
  • 对于 \(K = 1\):记 \(dp_{i, j, c_1}\) 表示已经考虑到 \(S_i, T_j\) 且答案串的末尾为 \(c_1\) 的最短长度。转移时对于一个字符 \(c\) 判断其是否能转移,该步也是平凡的。
  • 对于 \(K = 2, 3\),同理知在状态后面额外添加答案串的末尾字符即可。

当 \(K = 3\) 时上述状态设计复杂度最劣,为 \(O(n ^2 |\Sigma| ^3)\)。

对于这个状态进行观察,我们发现可以将末尾字符简单的归成四类:

  • 占位符,对后续状态没有限制。
  • 匹配 \(S_i\)。
  • 匹配 \(T_j\)。
  • \(S_i, T_j\) 都匹配。

进而分析可知,同一种类的字符转移方式时相似的。

基于该分析,我们可以优化状态:记 \(dp_{i, j, x, y, z}\) 表示已经考虑到 \(S_i, T_j\) 且答案串的末尾字符种类分别为 \(x, y, z\) 的最短长度。

转移可以简单的按是否为占位符分个类,自然是好写的。

重点在于判断非占位符是否能转移,记录状态中 \(S, T\) 的偏离步数即可。

P12458 [JOI2025 预选赛 R2] 冰淇淋 / Softcream

评级:普及+/提高-。

用时:\(60 \min\)。

题意转化为求:

\[\max_{i = 1} ^ x \min_{j = 1} ^ y \max_{k = 1} ^ z \{ |a_i + b_j + c_k - p| \} \]

显然 \(c_k\) 最大或最小时取到答案,式子进一步化为:

\[\max_{i = 1} ^ x \min_{j = 1} ^ y \max \{ |a_i + b_j + c_{max} - p|, |a_i + b_j + c_{min} - p| \} \]

不难发现 \(b_j\) 取绝对值内两式和一半的相反数上式取答案,简单二分即可。

P17089 掷出重围

评级:普及+/提高-。

用时:\(120 \min\)。

小观察:按 \(w_i\) 排序后投球一定不劣。

于是设 \(dp_{i, j, k}\) 表示前 \(i\) 物品,当前背包容量为 \(j\),最大价值为 \(k\) 的总贡献。

对于物品 \(i\) 的转移,按其是否大于现在的 \(k\) 分类转移,具体地:

  • 若 \(w_i > k\),\(dp_{i, j, k} \to dp_{i + 1, j + x_i, w_i}\)。
  • 否则 \(dp_{i, j, k} \to dp_{i + 1, j + x_i, k + 1}\)。

离散化 \(w_i\) 即可。

P10206 [JOI 2024 Final] 建设工程 2 / Construction Project 2

评级:普及+/提高-。

用时:\(30 \min\)。

枚举一条边 \((u, v)\),重连这条边合法的条件为:

\[dis_{s, u} + dis_{v, t} + l \le k \]

枚举一维维护一维即可。

P14799 [JOI 2026 二次预选] 比太郎之旅 3 / Bitaro's Travel 3

评级:普及+/提高-。

用时:\(30 \min\)。

注意到路径起点一定是奇数且奇偶性和步数相关,直接拆点为奇数点和偶数点即可。

P14798 [JOI 2026 二次预选] 购物 3 / Shopping 3

评级:普及+/提高-。

用时:\(60 \min\)。

直接二分 \(k\),可以对 \(a\) 序列分为两段算贡献,这个可以二分查找第一个大于 \(k \times d_j\) 的位置。

容易发现这个序列的贡献函数是一个下凸壳,其导函数斜率是单调递增的,在其上面二分即可。

P15823 [JOI Open 2013] 观影 / Watching

评级:普及+/提高-。

用时:\(120 \min\)。

\(w\) 越大,所需相机数量不减,可以对 \(w\) 二分。

这里的一个有效状态是形如 \((i, j, k)\) 形式的,表示到了第 \(i\) 个活动地点,使用了 \(j\) 个小型相机和 \(k\) 个大型相机。

可是这样设计状态无法进行有效的判断,不妨将可行性问题转换为最优化问题重新设计:记 \(dp_{i, j}\) 表示到了第 \(i\) 个活动地点,使用了 \(j\) 个小型相机所需的大型相机数,则最后只需检查 \(dp_{n, p}\) 是否大于 \(q\) 即可。

P16255 [DSTOI Round 0] 白石溪

评级:普及+/提高。

用时:\(60 \min\)。

划分序列的问题自然的想到 dp。题目中的两个限制框定了转移范围,轻松转移即可。

P15797 【MX-J28-T4】「Cfz Round 8」Color Problem

评级:提高+/省选。

用时:\(180 \min\)。

考虑如何设计状态转移才是完备的。需要知道当前在第几列,连通块大小和前几列的状态。基于该分析,我们得知让连通块所占的信息越少对我们而言是越有利的。所以可以设计 \(dp_{i, j, S}\) 表示第 \(i\) 当前连通块大小为 \(j\) 前面状态为 \(S\) 的染色方案。额外设计 \(f_i\) 表示连通块大小不超过 \(i\) 的染色方案数。这样答案是便于统计的,为:

\[\sum_{i = 1} ^ h f_i - f_{i - 1} \]

另外考虑状态之间的转移即可。这个可以较为简单的手模出来。

P16812 [蓝桥杯 2026 国 Python A] 压缩字符串

评级:提高。

用时:\(240 \min\)。

首先发现可以按 # 分段。不妨设第 \(i\) 段长度为 \(j\) 的字符串方案为 \(res_{i, j}\),那么答案实际上是对 \(res_{i, j}\) 做背包。

再来考虑段内的问题,其本质为求本质不同子序列方案数,直接求解即可。

P15289 「YLLOI-R3-T4」止战之殇

评级:普及+/提高。

用时:\(90 \min\)。

考虑求出两个怪兽之间最多能待几个回合,基于此一直向左跳到头再往右或向右跳到头再往左即可。

细节很多,考虑直接拼四个贪心上去。()

P15278 [MCO 2025] Subsequence

评级:提高。

用时:\(120 \min\)。

很弱智的 ds 优化 dp,感觉我初二就能做。

P15267 「UTOI 1B」Chaotic Time Trio

评级:普及+/提高-

用时:\(100 \min\)

不难发现无解的情况:

  • \(\{0, 0 \}\)。
  • \(\{ 0, 0, 0 \}\)。
  • \(\{ x(x > 0) \}\)。
  • \(\{ 0, x(x > 0) \}\)。
  • \(\{ x, y, z(x, y, z > 0) \}\)。

排除这些情况后,可以这样构造:

  • 钦定一个 \(x(x > 0)\)。
  • 将集合中 \(x\) 以外的数插入集合中,每次取最大值与次大值合并。
  • 可以证明最后答案为 \(0\)。

corner case:全 \(0\) 或全 \(x(x > 0)\) 序列可以先合并两项。

P14982 [USACO26JAN1] Supervision G

评级:提高。

用时:\(150 \min\)。

对教练 dp,转移为:

\[dp_i = \sum_j dp_j \times 2 ^ {cnt_j} \]

一个学员对教练的贡献是一段区间,这样我们维护区间乘法,区间求和即可。

P15059 [UOI 2023 II Stage] Product

评级:提高。

用时:\(100 \min\)。

很经典的题。钦定 \(a_i\) 为次小值,st 表 + 二分可以确定最大值位置。

知道了最小值和次小值位置之后可以继续 st 表 + 二分去扩展最长的区间。

P14981 [USACO26JAN1] Milk Buckets G

评级:提高。

用时:\(20 \min\)。

考虑阶段二的贪心:假设已经确定了合并顺序序列 \(a\),其贡献为:

\[\frac{1}{2 ^ {n}} \sum_{i = 1} ^ n 2 ^ {i - 1} \times a_i \]

可知从小到大填 \(a_i\) 上式最大。

再回来考虑阶段一:如何确定序列的最后形态。注意到第 \(i\) 次合并只要与第 \(i - 1\) 次合并相邻即可,那么就是对于一个递增的填数顺序,只要保证第 \(i\) 次填数放在第 \(i - 1\) 次填数的左右即可。这是一个单谷序列。

问题转化为上文的 Tricks 中的单谷序列内容。

P14969 They'll lead me to you

评级:提高。

用时:\(60 \min\)。

枚举 \(\operatorname{mex}\),序列划分为若干个不含 \(\operatorname{mex}\) 的区间,把这些询问挂在端点上即可。至于贡献的计算,可以用 BIT 轻松维护。

P15360 「WYZOI R2」烟花

评级:普及+/提高-

用时:\(105 \min\)。

模型是子序列 dp,难点在于 check 是否能转移。

注意到竖直距离不超过 \(d\) 这个条件可以转化为斜率区间,将枚举点上下平移算区间范围即可。

P16280 「MierOI R1」Eternal

评级:提高。

用时:\(120 \min\)。

考虑刻画区间形态,一定是一个极大区间左右端点包着几个小区间状物。

维护前缀状态和后缀状态,枚举一个断点,这样就可以统计出一个区间的信息了,而后是一个简单的子序列 dp。

ABC - E - Battles in a Row

评级:普及。

用时:\(3 \min\)。

可行性转最优性:\(dp_{i, j}\) 表示第 \(i\) 个怪剩余生命值为 \(j\) 的最少魔力值花费。

ABC - E - Maximum Glutton

评级:普及+/提高。

用时:\(5 \min\)。

可行性转最优性:\(dp_i\) 表示甜度为 \(i\) 时的最小咸度。

ABC - F - Must Buy

评级:普及+/提高。

用时:\(60 \min\)。

前后缀背包,钦定 \(i\) 的取舍以判断它的必要性。

ABC - F - Sensor Optimization Dilemma

用时:\(45 \min\)。

评级:普及+/提高-。

注意到枚举一种传感器的使用数量可以计算另一种的使用数量。记 \(dp_{i, j}\) 表示覆盖完前 \(i\) 段需要使用 \(j\) 个 \(1\) 类型传感器。而后枚举一个 \(k\) 作为第 \(i\) 段的使用数量,而后直接转移即可。

ABC - E - Warp

记 \(dp_{i, j, k}\) 表示方案 \(1, 2, 3\) 分别用了 \(i, j, k\) 次。std :: set 判掉障碍点即可。

ABC - E - Subarray Sum Divisibility

用时:\(45 \min\)。

评级:普及+/提高-。

发现序列的最终态一定是 \(a_i\) 与 \(a_{i + L}\) 同余,可以预处理出 \(val_{i, j}\) 表示模 \(L\) 为 \(i\) 的位置模 \(m\) 为 \(j\),背包合并这一坨即可。

ABC - F - Monochromatic Path

用时:\(45 \min\)。

评级:普及+/提高-。

注意到对一行或一列进行大于一次操作是无意义的,因此我们定义 \(dp_{i, j, x, y}\) 表示走到点 \((i, j)\) 且第 \(i\) 行第 \(j\) 列是否被操作的最小费用。显然第 \(i\) 行能被操作的条件是第 \(i - 1\) 行的同列元素与其颜色相反。对于列同理。如此转移即可。

ABC - E - Don't Isolate Elements

用时:\(45 \min\)。

评级:普及+/提高-。

假如我们要考察第 \(x\) 行是否合法,我们需要得知第 \(x - 1. x +1\) 行的信息才能判断。依此设计 \(dp_{i, x, y}\) 表示到第 \(i\) 行且已经确定了前 \(i - 1\) 行且第 \(i\) 行是否被操作,第 \(i - 1\) 行是否被操作的合法的最小操作数。转移时枚举 \(i - 1\) 的 dp 状态即可。

ABC - G - AtCoder Tour

用时:\(45 \min\)。

评级:普及+/提高-。

考虑最后的答案形式,一定是走到某一个点并且一直待着不在走动的形式。而从起点到任意一个点所走动的距离一定不超过 \(n \times m\) 步。因此设 \(dp_{i, j, k}\) 表示到点 \((i, j)\) 走了 \(k\) 步的最大乐趣值(不加等待时间)。随便转移即可。

ABC - F - Shortcuts

用时:\(45 \min\)。

评级:普及+/提高-。

一个经典的序列划分 dp。观察到至多跳过 \(O(\log V)\) 个点,因此只需要 \(O(\log V)\) 枚举上一位,\(O(\log V)\) 判断合法性即可。

ABC - F - Prefix LIS Query

用时:\(45 \min\)。

评级:普及+/提高-。

注意到询问 \(X_i\) 对我们的限制是最紧的,于是我们离线后用按值从小到大插入,线段树转移即可。

ABC - F - |LIS| = 3

用时:\(45 \min\)。

评级:普及+/提高-。

因为合法序列的 LIS 长度不超过 \(3\),且观察到值域不超过 \(10\)。所以不妨设 \(dp_{i, x, y, z}\) 表示已经填完前 \(i\) 位,当前合法的 LIS 是 \((x, y, z)\) 的情况。转移只需枚举一个数 \(w\) 替换 \((x, y, z)\) 中的一个即可。

ABC - F - Simple Operations on Sequence

用时:\(90 \min\)。

评级:普及+/提高-。

是一个经典题。考虑往已选集合里面添加一个单点的代价即可。

DP - V - Subtree

用时:\(90 \min\)。

评级:普及+/提高-。

设计 \(\operatorname{sub}(x)\) 和 \(U \backslash \operatorname{sub}(x)\) 的状态,换根时发现贡献是形如排除 \(\operatorname{sub}(x)\) 中的某个点,前后缀优化即可。

G - Vertex Deletion

用时:\(45 \min\)。

评级:普及+/提高-。

结论是最大匹配等于总点数减最大独立集,问题转化为树上最大独立集。

ABC - F - Treasure Hunting

用时:\(45 \min\)。

评级:普及+/提高-。

考虑钦定 \(a_{x, y}\) 为第 \(K\) 大整数,设 \(dp_{i, j, k}\) 表示走到点 \((i, j)\),选完了前 \(k\) 大整数的最小代价。转移比较 navie。

ABC - G - Divide a Sequence

用时:\(45 \min\)。

评级:普及+/提高-。

可以分成两个部分分别 dp,单调栈转移即可。

ABC - F - Two Exams

用时:\(45 \min\)。

评级:普及+/提高-。

很舒服的题目,根据偏序关系转移即可。

ABC - E - RLE

用时:\(45 \min\)。

评级:普及+/提高-。

设 \(dp_{i, j}\) 表示前 \(i\) 位替换成长度为 \(j\) 的字符串的方案数,有转移:

\[dp_{i, j} \to dp_{i + len, j - (f(len) + 1)} \]

其中 \(f(len)\) 表示 \(len\) 在十进制下的位数。

发现 \(f(len)\) 只有 \(4\) 种取值,对于每一种转移前缀和即可。

ABC - G - Pre-Order

用时:\(45 \min\)。

评级:普及+/提高-。

简单区间 dp。对于右子树新建虚拟节点即可。

P13009 【MX-X13-T4】「KDOI-12」好胜是人的本能,功利是社会的本性。

用时:\(45 \min\)。

评级:普及+/提高-。

注意到至多只会操作 \(2\) 次,于是可以设 \(dp_{i, j}\) 表示到第 \(i\) 位且第 \(i\) 位操作了 \(j\) 次的最小操作数。

P13010 【MX-X13-T5】「KDOI-12」茫茫人海如都市的晚高峰,迎面的车终将相遇,迎面的车终将分别。

用时:\(45 \min\)。

评级:提高。

注意到调配的约束随着最大负载量的减少而加紧,所以我们可以二分最大负载量,模拟分配车道的过程即可。

P14378 【MX-S9-T1】「LAOI-16」签到

用时:\(45 \min\)。

评级:提高。

首先原序列可以变为一个新序列,对新序列排序。对于一个修改,找到其在新序列上的位置,序列被分为三段,对于每一段简单算一下贡献即可,可以画图模拟一下。

P13732 【MGVOI R1-D】图上的数(graph)

咕一下。

P13562 「WWOI R1」WsW 的田地

用时:\(45 \min\)。

评级:提高。

对于差分数组随机赋权哈希即可。

Div. 1 C. XOR Inverse

用时:\(45 \min\)。

评级:提高。

对原序列建出 01 trie,那么 01 trie 上保证了 \(a_i < a_j\) 的偏序,我只要统计横跨左右子树的逆序对即可。

Div.2 E. Marbles

用时:\(45 \min\)。

评级:提高。

可以预处理出一个颜色挪到一个颜色集合前面的代价,而后 dp 即可。

Div. 2 D. Hot Start Up

D1

用时:\(30 \min\)。

评级:普及+/提高-。

设 \(dp_{i, j}\) 表示两个 CPU 分别以 \(a_i, j\) 结尾的代价,分类转移。

D2

用时:\(45 \min\)。

评级:提高。

压维后,转移可视作全局加,单点修改,前缀查询。线段树维护即可。

VK CUP C. Monsters

题目转化为维护一个首项、公差为 \(1\) 的等差数列。

这个可以挂到值域线段树上维护。

Div. 2 E. AND-MEX Walk

一个重要的观察:答案不超过 \(2\)。

对于答案分别为:\(0, 1, 2\) 的情况分别考察,可以按位维护并查集。这样答案的取值可以用并查集的连通性统计出来。

Div. 1 + Div. 2 D. New Year and Conference

本质上还是偏序的套路,枚举左端点维护右端点即可。

Div. 1 B. A Lot of Games

建出 Trie,叶子节点是必败态。跟据这个可以推出其它节点的可胜态和可败态。

Div. 1 C. Limited Edition Shop

按照原顺序是不好做的,考虑按 Alice 顺序做。

设计 \(dp_{i, j}\) 表示按该顺序 Alice选完前 \(i\),Bob 选了 \(j\) 个的代价。记 \(pos_i\) 表示 Bob 对应的 Alice 的下标,有刷表转移:

\[dp_{i, j} + v_i \to dp_{i + 1, j} \]

\[dp_{i, j} \to dp_{i + 1, pos_i} \]

一个全局加一个单点修,线段树维护转移即可。

Div. 2 E. A Trivial String Problem

简单的 Border dp。

Div. 2 E. Predicting Popularity

维护一棵值域线段树,线段树维护 \(\max(a_i - ac, 0) + \max(d_i - dr, 0)\) 的值。每次修改相当于后缀加,查询则是在线段树上查询第一个 \(\max(a_i - ac, 0) + \max(d_i - dr, 0) \geq i\) 的位置,线段树上二分即可。

Div. 1 C. Revival

限制从后往前逐步加紧,不妨倒序确定元素。这样是可以二分出当前元素的,至于判重,使用并查集即可。

Div. 2 E1. Looking at Towers (easy version)

\(L(h), R(h)\) 的交一定是 \(\max h_i\)。因此先求出 \(L(h), R(h)\),在位置 \(x(h_x = \max h_)\) 进行决策,就是一个简单的双序列 dp。

Div. 2 E. Simons and Dividing the Rhythm

划分序列 dp。设计 \(dp_i\) 表示前 \(i\) 位操作后得到的新字符串方案数。但是这样做是要去重贡献的。我们思考问题的最小子问题:若一个区间被翻转,其任意子区间没有除翻转该区间的其他方案到达该翻转状态,则这个区间的翻转贡献有且仅有这一次。我们称这种区间为最短合法区间

那么我们可以更改状态设计:\(dp_i\) 表示前 \(i\) 位只翻转最短合法区间所得新字符串方案数。记区间 \([l, r]\) 的最长 border 的长度为 \(\pi_{[l, r]}\),则区间为最短合法区间当且仅当 \(\pi\) 值为 \(0\)。

Div. 1 B. Strange Definition

\[K = \frac{\operatorname{lcm}(x, y)}{\gcd(x, y)} = \frac{x \times y}{\gcd ^ 2 (x, y)} \]

当且仅当 \(x \times y\) 为完全平方数时 \(K\) 为完全平方数。

那么对于一个 \(x\),将其唯一分解为 \(\prod p_k ^ {c_k}\) 的形式,令 \(S\) 为满足 \(2 \nmid c_k\) 的 \(k\) 的集合,那么统计每一个 \(x\) 的 \(\prod_{k \in S} p_k\) 即可,记这个值为 \(\operatorname{val}(x)\)。

由于相邻的数操作后会变为它们的乘积,因此只有操作一次或不操作是有效的。

对于不操作的部分,答案为 \(\operatorname{val}(x)\) 出现次数的最大值。

对于操作一次的部分,答案为 \(\operatorname{val}(x) = 1\) 的出现次数加 \(\operatorname{val}(x)\) 的出现次数整除 \(2\) 的出现次数之和。

Div. 3 G. Strange Beauty

排序后是一个子序列 dp,按值域记录 dp 即可 \(O(n \sqrt n)\) 做。

Div. 1 B. Nezzar and Binary String

倒着做,线段树模拟即可。

Div. 2 D. Sum of Paths

你可以轻易 dp 出 \(a_i\) 贡献了几次。

Div. 1 D. Strange Housing

直接黑白染色即可。

Div. 2 E. Minimum Path

由于 dijkstra 是基于贪心实现的,我们可以直接建出分层图跑最短路。

Технокубок F. Useful Edges

首先有一种显然的 \(O(mQ)\) 复杂度的做法。

枚举一条边,check 其断掉之后的贡献是否合法:\(dis_{x, u} + w + dis_{v, y} \le l\)。

其中 \((u, v, w)\) 为原图上的一条边,\((x, y, l)\) 为一组询问。

运用偏序问题中常用的“枚举一维维护一维”的思想,我们不妨只枚举一个询问的其中一个端点 \(x\)。

围绕我们枚举的 \(x\),可以将上述式子化为:

\[dis_{x, u} + w \le l - dis_{v, y} \]

此时左边式子的值因为已经枚举了,所以能轻松算出来,相当于一个定值。我们只需要让这个定值小于右边式子的最大值即可。

所以,当前问题转化为求 \(l - dis_{v, y}\) 的最大值。注意到 \(l, y\) 是同时枚举的(同属一个询问),那么在此基础上再枚举点 \(v\) 就能算出该值。

再来考察复杂度。check 式子 \(O(nm)\),预处理 \(O(nQ)\),总时间复杂度 \(O(n(m + Q))\)。

ABC - F - Road Blocked

倒着做,新增一条边可以 Floyd \(O(n)\) 添加贡献。

ABC - E - Development

机场点可以连虚点。

P14379 【MX-S9-T2】「LAOI-16」摩天大楼

刻画答案形态,是形如不含 \(1\) 的子段或者含 \(1\) 不含 \(2\) 的子段。利用 std :: set 可以轻松维护。

Div. 2 G. Xor-MST

建出 01 Trie。经过的重复路径是没有贡献的,换而言之,我们只需要对于一个节点统计其横跨左右子树的贡献即可。我们可以自上而下地合并,相当于是一个延迟决策的操作。

Div. 2 E. Chaotic Merge

考虑我们只需求 \(f(1, |x|, 1, |y|)\) 怎么做。设计 \(dp_{i, j, k}\) 表示 \(x\) 串选完前缀 \(i\),\(y\) 串选完前缀 \(j\),上一次选的是 \(x\) 串还是 \(y\) 串的数量。可以直接转移。答案是 \(dp_{|x|, |y|, 0} + dp_{|x|, |y|, 1}\)。

现我们要求所有子段的 \(f\) 值之和,那么我们可以钦定一个起点 \((i, j)\)。落实到代码中就是状态 \((i, j)\) 的初始值设为 \(1\)。为了避免算重,我们可以在 \(dp\) 中再维护一个维度 \(S\) 表示 \(x, y\) 串是否被选过。状态转移还是类似于下一位选 \(x\) 串和选 \(y\) 串的贡献统计。

实现采用刷表会更为简便。

Div. 2 F. Comfortably Numb

结构很容易让人联想到笛卡尔树。我们需要保证插入、删除的复杂度,只需要在分治的时候把较短区间的异或前缀和插入 01 Trie,并在通过笛卡尔树的一条轻边的时候清空即可。

ICPC L. Project Manager

一个需要逻辑自洽的模拟题,代码不长但是思考细节极多。

Div. 2 D. MEX Tree

可以比较 tricky 的设计 \(f_i\) 表示 \(\operatorname{mex} \le i\) 的答案。对于 \(i = 0, 1, 2\),可以特殊地统计。对于 \(i \geq 3\),相当于是在维护树上一条链。这样往下走的时候可以稍微分类讨论一下。直接维护右链可以降低分讨难度。

Div. 2 E2. Abnormal Permutation Pairs (hard version)

枚举 \(p, q\) 相同前缀长度,后面我们只关心相同前缀后的第一位数字和逆序对总数。然后可以推一推式子就可以知道你能通过前缀和优化这一个过程。

如果想到了枚举差值将会无路可走了,这是一个比较坑的地方。

Div. 2 F. Korney Korneevich and XOR

F1

考虑设计 \(dp_{x}\) 表示子序列异或值为 \(x\) 的最小末尾元素,则直接转移可以做到 \(O(nV)\)。

F2

F1 的做法实质上是一个集合对点的映射。不妨将映射关系改为一个点映射一个集合。具体而言,设计 \(dp_{x}\) 表示结尾元素值大于等于 \(x\) 的子序列的异或值集合。可以用类似 BFS 的过程转移,一个值至多被到达 \(O(V)\) 次,则总时间复杂度 \(O(n + V ^ 2)\)。

Technocup E. Frequency Queries

在线做比较困难,不妨将询问离线下来。

由于查询实际上是根到某个节点的一条链,我们只需要在 dfs 的时候维护即可。我们按出现次数开一棵值域线段树,同时在叶子节点维护一个 std :: set 用来存该出现次数所有点权。每次到达一个节点将其出现次数加一并将其在线段树上修改,回溯时删除信息即可。

查询相当于是找超过某个数的第 \(k\) 大值。这个是一个前缀查询和线段树上二分。前面所说的插入和删除操作是单点修改,在线段树上维护这几个操作即可。

Technocup F. Non-equal Neighbours

容斥,则是一个恰好转钦定。设钦定 \(i\) 个位置相等的答案是 \(f_i\),则答案为:

\[\sum_{i = 0} ^ n (-1) ^ i f_i \]

然后是一个经典的划分序列 dp,可以单调栈 + 滚动数组优化。

Div. 2 F. RBS

看到 \(n \le 20\),可以考虑 \(O(2 ^ n)\) 的算法。

可以设计 \(dp_S\) 表示选择字符串集合为 \(S\) 拼接而成的字符串前缀合法括号序列最多的数量。

还是套路地将 ( 赋为 \(1\),) 赋为 \(-1\)。那么如果拼接的字符串存在一个前缀和小于 \(0\) 的位置则它不可能继续往后拼接新的字符串,但是它可以计入答案。

所以,我们对于每一个字符串维护最小前缀和的值、某一个前缀和的出现次数和在最小前缀和之前某一个前缀和的出现次数即可。

Div. 2 D. Red-Blue Matrix

一个方案合法的必要条件是其第一列合法。于是我们将原矩阵按第一列排序,这样我们可以直接枚举分界点判断是否合法。对于合法的判断,维护四个方向的前后缀最值即可。

Div. 1 + Div. 2 E. William The Oblivious

首先可以把三元组问题拆分为二元组问题,而后又可以将其拆分为单个元素的问题。

我们把这一坨东西丢到线段树上。维护 a, b, c 出现的数量,和使得 ab, bc, abc 不出现所需的最少操作数。以维护 ab 为例,在合并的时候删去左儿子的 a 或者右儿子的 b 一定是最优的,加上另一个儿子的答案即可。其它的情况可以以此类推。

Div. 3 H. Permutation and Queries

考虑弱化问题:不带修怎么做。这样可以直接倍增 \(O(n \log n)\) 预处理,询问 \(O(1)\) 查询。那么加上带修我们就需要考虑一个更折中的办法平衡预处理、修改和查询的复杂度,可以使用操作分块或者根号分治。这里实现使用的根号分治。

Div. 2 E. Black and White Tree

钦定某个点为根时,一个点合法的条件为其子树黑点数量大于等于 \(2\) 且在一条链上或与其距离最近的黑点距离不超过 \(1\)。

设计 \(dp_x\) 表示 \(x\) 点是否能到达黑点。将所有距离黑点不超过 \(1\) 的邻域内的所有点 \(u\),赋值 \(dp_u \to \texttt{true}\)。设 \(sz_x\) 表示 \(x\) 子树内黑点的数量。则:

\[dp_x = dp_u \land [sz_x > 1] \]

换根同理。

Div. 1 D2. Game on Sum (Hard Version)

可以设计 \(dp_{i, j}\) 表示第 \(i\) 轮,Bob 用了 \(j\) 次加法的答案。又因为博弈论 dp 从初始状态开始是不好转移的,不妨从终止状态开始。那么我们更改状态设计,设计 \(dp_{i, j}\) 表示还剩 \(i\) 轮,Bob 还需要用 \(j\) 次加法的答案。

有:

\[dp_{i, j} = \max \{ dp_{i - 1, j} - x, dp_{i - 1, j - 1} + x \} \space (x \in [0, k]) \]

由于两人决策一定最优,所以:

\[dp_{i, j} = \frac{dp_{i - 1, j} + dp_{i - 1, j - 1}}{2} \]

初始状态为 \(dp_{i, 0} = 0, dp_{i, i} = i \times k\),答案为 \(dp_{n, m}\)。

时间复杂度 \(O(nm)\)。

考虑 \(dp_{i, i}\) 对答案的贡献。不妨将 \((i, i)\) 和 \((n, m)\) 刻画为网格图上的点,每次可以向下或向右下走。那么从 \((i, i)\) 这样走到 \((n, m)\) 的方案数是 \(\binom{n - i - 1}{m - i}\)。步数总数为 \(n - i - 1\) 的原因是因为 \((i, i)\) 是边界值。

那么答案为:

\[k \times \sum_{i = 1} ^ m \frac{i \times \binom{n - i - 1}{m - i}}{2 ^ {n - i}} \]

时间复杂度 \(O(n + m)\)。

Div. 1 D. Flipping Range

更相减损术,长度集合 \(S\) 内可以存在的数为 \(k \times \gcd_{x \in B}(x)\),其中 \(B\) 为原集合,\(k\) 为某个正整数。

设 \(S\) 内最小元素为 \(x\),则 \(x = \gcd_{x \in B}(x)\)。我们可以将位置模 \(x\) 分类。操作可以改为 \(i, i + x\) 两个点取反。设 \(cnt_i\) 表示模 \(x\) 后值为 \(i\) 的负数个数。若 \(cnt_i\) 为奇数,则只会剩下一个留下绝对值最小的负数,否则可以不留下负数。还有一个 corner case 是,你可以先剔除前 \(x\) 个数,这样奇偶性可以互换。

Div. 2 E. Spanning Tree Queries

简要题意

给定一张无向图,边集权值为 \(w_i\)。需要回答若干个询问,每个询问给出 \(x\)。定义一棵生成树的代价为 \(\sum_{i \in E} |w_i - x|\),其中 \(E\) 为边集。求原图中所有生成树的最小代价。强制在线。

思路

假如只考察询问 \(x\) 的一个极长区间 \([L, R]\)(即 \(x \in [L, R]\)),满足该区间只有两种最小生成树形态。那么临界点自然是取 \(\frac{L + R}{2}\)。显然,这两种最小生成树形态只会有恰好一条边不同。进而可以发现,端点 \(L, R\) 实际上就是两条边的权值 \(w_i, w_j\)。所以,对于任意询问 \(x\) 而言,其实只有 \(O(m ^ 2)\) 中最小生成树形态,可以事先预处理,时间复杂度 \(O(m ^ 3 \log m)\)。对于一个询问 \(x\),可以直接二分找到 \(x\) 对应的最小生成树形态,而后可以 \(O(1)\) 增删贡献。

Div. 2 E. Spanning Tree Queries

思路

可以 \(i \to (i + n - d) \operatorname{mod} n\) 建边,每次扩展到为 \(0\) 的位置即可。这个是可以 BFS 简单维护的。轮数可以统计 BFS 了几层。

Div. C. Moamen and XOR

思路

可以对小于和等于的方案分别计数,答案为:

  • 奇数:

\[(2 ^ {n - 1}) ^ k + \sum_{i = 1} ^ k (2 ^ {n - 1}) ^ {i - 1} \times (2 ^ {n}) ^ {k - i} \]

  • 偶数:

\[(2 ^ {n - 1} - 1) ^ k + \sum_{i = 1} ^ k (2 ^ {n - 1} - 1) ^ {i - 1} \times (2 ^ {n}) ^ {k - i} \]

犯错

  • 未讨论奇偶性。
  • 奇偶性讨论反了。

Div. 2 C. The Sports Festival

简要题意

给定序列 \(a\),你可以任意排列 \(a\) 的顺序。令 \(d_i = \max_{j = 1} ^ i a_j - \min_{j = 1} ^ i a_i\)。求:$ \min \sum_{i = 1} ^ n d_i$。

思路

  • 最优方案一定是把 \(\max a_i\) 或 \(\min a_i\) 放到最后。

证明:由于选择的是一段前缀,那么最值靠前会使得极差大的值变多。

那么将 \(a\) 排序后选择的将会是一段区间,且每次只会扩展左右端点,可以 \(O(n ^ 2)\) 区间 dp。设 \(dp_{i, j}\) 表示前 \(j - i + 1\) 个数选择区间 \([i, j]\) 的数,那么转移为:

\[dp_{i, j} = \min \{ dp_{i + 1, j}, dp_{i, j - 1} \} + a_j - a_i \]

犯错

  • 往差分的方向去思考了,没有刻画答案的形态。

Div. 2 E. Make Good

简要题意

给定一个长度为 \(n\) 的括号字符串 \(s\)。若干次以下操作:

  • 选择一个下标 \(1 \leq i < |s|\),若 \(s_i = s_{i + 1} = (\),则将 \(s_i\) 和 \(s_{i + 1}\) 都替换为 \()\)。
  • 选择一个下标 \(1 \leq i < |s|\),若 \(s_i = s_{i + 1} = )\),则将 \(s_i\) 和 \(s_{i + 1}\) 都替换为 \((\)。

找出一个可以通过上述操作从 \(s\) 得到的合法括号序列 \(t\) 或报告无解。

思路

(() 可以转化为 )((,))( 可以转化为 ())。那么可以把这种变换看作将单括号提到两个相同括号前。并且我们还可以进一步从两个相同括号拓展为多个连续相同且连续数量为偶数的括号,这一步是比较显然的。

依照这个性质,我们可以将一个单括号提到极长的连续相同且连续数量为偶数的括号前,并删除这些连续括号。迭代进行操作直到不再出现连续相同且连续数量为偶数的括号即可。

犯错

  • 没有想到上述转化实际上是括号的移动,导致多了很多不必要的特判。
  • 可以在输入的时候直接判掉所有偶数括号,这样可以避免 while(true)。

Div. 3 G2. Big Wins! (hard version)

简要题意

求:\(\max_{l, r \in [1, n], l \le r} \{ \operatorname{med}_{i = l} ^ r \{ a_i \} - \min_{i = l} ^ r \{ a_i \} \}\),其中 \(\operatorname{med}\) 表示中位数。

思路

考虑枚举中位数,设当前枚举到 \(x\)。可以套路的维护序列 \(b\),使得若 \(a_i < x\) 时 \(b_i = -1\) 否则 \(b_i = 1\)。若 \(\operatorname{med}_{i = l} ^ r \{ a_i \} \geq x\) 当且仅当 \(\sum_{i = l} ^ r b_i \geq 0\)。

令 \(pre\) 为 \(b\) 的前缀和序列。对于我们枚举的一个 \(a_i\),若 \(\max_{j \in [i, n]} pre_j - \min_{j \in [1, i - 1]} pre_j \geq 0\),则 \(a_i\) 有贡献。我们从大到小枚举 \(a_i\),则 \(\max_{j \in [i, n]} pre_j - \min_{j \in [1, i - 1]} pre_j\) 单调不降。那么我们可以在线段树上二分出两个极值的所在位置 \(posl, posr\)(\(\max\) 式子取位置最大值,\(\min\) 式子取最小值),则 \(a_i\) 可以在区间 \([posl, posr]\) 中充当中位数。则答案为:\(\max_{i = 1} ^ n \{ a_i - \min_{j \in [posl, posr]} a_j \}\)。

犯错

  • 维护序列 \(b\) 可以判断是否能成为中位数这个套路没见过。
  • 注意区间开闭,浪费了 30 min。

Div. 3 H. Shiori Miyagi and Maximum Array Score

简要题意

给定 \(n, m(n \le m)\)。在所有满足下述条件的长度为 \(n\) 的序列 \(a\) 中,找到 \(\sum_{i = 2} ^ n v(i, a_i)\) 的最大值:

思路

  • \(a\) 严格递增。
  • \(\forall i \in [1, n]\),都有 \(1 \leq a_i \leq m\)。

其中 \(v(x, y)\) 为满足 \(x ^ k \mid y\) 的最大 \(k\)。

设计 \(dp_{i, j}\) 表示前 \(i\) 位且第 \(i\) 位为 \(j\) 的最大价值。有状态转移:

\[dp_{i, j} = \max_{k = 1} ^ {j - 1} dp_{i - 1, k} + v(i, j) \]

其中第一维可以直接压缩掉。

  • 状态总数是 \(O(n \ln n)\) 的。

证明:\(v(i, j) = 0\) 只会继承前面的状态,否则是一个新状态。而 \(v(i, j)\) 的取值总数是调和级数级别的。

但是 \(v(i, j) = 0\) 的部分实际上也是有效的。于是我们更改状态设计:\(dp_j\) 表示当前位为 \(i + j\) 的最大价值,则:

\[dp_j = \max_{k = 1} ^ {j} dp_k + v(i, i + j) \]

那么 \(v(i, i + j) = 0\) 的部分会继承之前的 dp。问题转化为单点修改、前缀 \(\max\),树状数组可以轻松胜任。

另外决策点集合可以用一个 vector 维护。

Div. 1 + Div. 2 D. Traffic Lights

简要题意

给定一张无向连通图。初始时刻 \(0\) 时有一个人位于点 \(1\)。若在时刻 \(t\) 时这个人在点 \(x\),则他有两种选择:

  • 等待 \(1\) 秒。
  • 花费 \(1\) 秒到达点 \(x\) 连接的第 \(t \bmod deg(x) + 1\) 个点。(点的顺序是题目输入顺序)

求这个人到点 \(n\) 所需的最短时长,在此基础上最小化等待时间。

思路

设计 \(dp_{i, j}\) 表示从点 \(1\) 到点 \(i\) 消耗时间 \(j\) 所需的最短等待时长。有转移:

\[dp_{i, j} + 1 \to dp_{i, j + 1} \]

\[dp_{i, j} \to dp_{to(i, j \bmod deg_i), j + 1} \]

其中 \(to(i, j)\) 表示点 \(i\) 连接的第 \(j\) 个点。

我们发现该做法复杂度和步数强相关,考虑分析步数上界。记步数为 \(s\)。

  • \(s \le n \times m\)。

相当于你把整张图都遍历了一遍。

  • \(s \le 3 \times n\)。

以 \(1\) 为起点建出 BFS 树。记 \(S_i\) 表示树上深度为 \(i\) 的节点集合。则从 \(S_i\) 通过一条边只能到达 \(S_{i - 1}, S_i, S_{i + 1}\)。显然可以构造一条路径 \(1 \rightsquigarrow n\) 满足其经过的边都在 BFS 树上。路径上每个节点至多等待的时间为 \(deg_i - 1\)。设路径上的点集为 \(T\),则有不等式:

\[s \le \sum_{x \in T} (deg_x - 1) \le \sum_{i = 1} ^ {|T|} |S_{i - 1}| + S_i + |S_{i + 1}| \le 3 \times n \]

于是得证。

Div. 2 E. Colorful Operations

简要题意

区间推平颜色,单点颜色 \(+ k\),单点查询。

思路

在此学会了势能分析法。简要证明:颜色端总数是 \(O(Q)\) 的,因此暴力修改即可。具体证明是分析两次操作状态的势能差,需要构造势能函数。

Div. 2 D. Dog Walking

简要题意

给定一个序列,有若干位置不确定,不确定的位置可以在 \([-k, k]\) 中任取。问序列的最大前缀和减最小前缀和的最大值。

思路

无解条件是不确定部分全部取 \(k\) 的和小于已确定部分和的绝对值。然后我们可以对于每一个区间钦定其全部选 \(k\) 或 \(-k\),取最大值即可。

Div. 2 D. Tree XOR

简要题意

给定一棵树,你可以选择一棵子树使得子树内所有点异或上一个值 \(x\),其代价为子树大小乘 \(x\)。对于每一个 \(i\) 计算当以 \(i\) 为根时使得所有 \(a_i\) 的最小代价。

思路

如果你确定了一棵树的形态,那么这棵树的贡献是一定的。换根即可。

Div. 3 G. Rudolf and CodeVid-23

简要题意

有 \(n\) 个症状 \(m\) 种药,每种药可以消除某个状态集合和新增某个状态集合。每天只能用一个药且药的数量无限。计算消除所有症状所需的最短天数。

思路

考虑直接状压症状集合。将每一个症状状态都当做一个点,则药品可以看成一条边。实质上是一个最短路建模。

Div. 2 D. Black Cells

简要题意

给定 \(n\) 个不相交且相互之间距离至少为 \(1\) 的区间,对某个区间的子区间 \([l, r]\) 染色的代价为 \(r − l + 3\),求总染色长度为 \(k\) 时的最小花费。

思路

  • 选择长度大于 \(1\) 的区间一定不劣。

证明:假设不选一个长度为 \(x(x > 1)\) 的区间 \([l, r]\),对 \([l, r]\) 染色减少的代价至少为 \(x\),选择这段区间增加的代价为 \(2\)。由于 \(x > 1\),所以答案一定不劣。

维护长度为 \(1\) 的区间数量,选择长度大于 \(1\) 的区间即可。这样只要模拟即可。

Div. 1 C. Pokémon Arena

简要题意

\(n\) 个宝可梦在竞技场,每个宝可梦有 \(m\) 个属性,第 \(i\) 个宝可梦的第 \(j\) 个属性记为 \(a_{i, j}\),每次决斗赢的宝可梦留在擂台上,输的宝可梦下场,\(x\) 能打败 \(y\) 当且仅当存在某个 \(k\) 使得 \(a_{x, k} \geq a_{y, k}\)。第 \(i\) 个宝可梦出场需花费 \(c_i\),可以花费 \(p\) 将某个宝可梦的某个属性永久提升 \(p\),一开始第 \(1\) 个宝可梦在擂台上,问要使第 \(n\) 个宝可梦在擂台上的最小花费。

思路

可以比较显然的发现大概是一个最短路建模的题目。将第 \(i\) 个宝可梦的第 \(j\) 个属性抽象为一个点进行考虑。

  • 相邻两次决斗中的 \(j\) 不同。

证明:假设相邻两次决斗中,先用 \(y\) 的 \(i\) 属性打败了 \(x\),再用 \(z\) 的 \(i\) 属性打败了 \(y\),那么直接用 \(z\) 的 \(i\) 属性打败 \(x\) 可以节省 \(c_y\) 的出场费,并且后者所需要提升的属性不多于前者,即后者一定更优。

于是用 \(y\) 的 \(i\) 属性打败 \(x\) 所需提升的能力值永远是 \(\max(0, a_{y, i} − a_{x,i})\)。因此可以 \((x, i) \to (y, i)\) 连一条权值为 \(\max(0, a_{y, i} − a_{x,i})\) 的边。

我们可以把所有属性值单独拎出来考虑,那么我们可以按属性值对 \(n\) 个点排序,每个点只向相邻的点连边。

至于出场费,我们考虑拆点,这样可以将点权转边权。

Div. 1 D1. Counting Is Fun (Easy Version)

简要题意

定义好序列为能通过若干次区间减 \(1\) 且区间长度大于 \(1\) 操作得到全 \(0\) 的序列。求长度为 \(n\),至于为 \(k\) 的好序列数量。

思路

  • 对于任意 \(a_i \geq a_{i - 1} + a_{i - 2}\) 才合法。

证明:对原序列求差分序列,问题转化为在选择点不相邻的情况下选两个点,且前一个减一后一个加一,让 \([1, n + 1]\) 全部变成 \(0\)。有一个很显然的思路是用前面的正数去消去后面的负数。我们设 \(dif\) 为原序列的差分序列,那么能完全消去当且仅当 \(\sum_{j = 1} ^ {i - 2} dif_j \geq -dif_i\)。再把 \(dif\) 化为 \(a\),则上式改写为:\(a_{i - 2} \geq -a_i + a_{i - 1}\),即 \(a_i \geq a_{i - 1} + a_{i - 2}\)。

问题转化为统计 \(a_i \geq a_{i - 1} + a_{i - 2}\) 的数量。可以设计 \(dp_{i, j, k}\) 表示前 \(i\) 个数,末尾两个数分别为 \(j, k\) 的合法方案数。转移是比较显然的,可以用前缀和优化。

Div. 2 E. Unique Array

简要题意

定义好序列为存在恰好出现一次的数的序列,可以替换序列中某个数为任意整数。求使得 \(a\) 的子段都成为好子序列所需的最少操作次数。

思路

题目可以转化为选择尽可能少的点使得以这些点作为断点且挖去后分隔的子段合法。

首先有一个显然的贪心是若枚举到一个不合法前缀可以直接钦定其为断点。那么再去考虑如果判断一个子段是否合法。

维护一个前缀指针 \(pos\)。记 \(i\) 位置的值上一次出现位置为 \(lst_i\),那么枚举到 \(i\) 时将区间 \([lst_{lst_i} + 1, lst_i] - 1, [lst_i + 1, i] + 1\)。若区间 \([pos, i]\) 中出现了 \(0\) 则该前缀不合法,令答案加一,\(pos \to i + 1\) 即可。

Div. 1 B2. Range Sorting (Hard Version)

简要题意

定义一次操作为升序排序一个区间,其代价为区间长度减一。定义一个序列的权值为用若干次操作使得序列升序的操作代价总和。求 \(a\) 的所有子段的权值和。

思路

  • 操作一定不相交。

证明:假设存在两个相交的操作 \([l_1, r_1], [l_2, r_2](l_1 \le l_2 \le r_1 \le r_2)\) 可以将区间 \([l_1, r_2]\) 排好序,其贡献为:\(r_1 - l_1 + r_2 - l_2\)。那如果我直接操作 \([l_1, r_2]\) 其贡献为:\(r_2 - l_1\)。贡献 \(\Delta = r_1 - l_2\),显然 \(\Delta \geq 0\),贡献不降且排序后效果没变。因此操作一定不相交。

考虑用总贡献减去额外贡献。总贡献为:

\[\sum_{i = 1} ^ n (i - 1) \times (n - i + 1) \]

考虑什么时候会出现额外贡献。若一个区间操作可以拆分成若干个小区间操作,则会减少贡献。并且操作数每增加 \(1\),总贡献减少 \(1\)。

先考虑只把一个区间拆分成两个。钦定 \(a_i\) 为某个区间的前缀最大值,那么该区间能被拆分当且仅当区间的后缀最小值大于 \(a_i\)。

考虑对上述区间计数。我们枚举 \(a_i\),令 \(l_1\) 表示 \(i\) 往前第一个位置,其值大于 \(a_i\),\(r_1\) 表示 \(i\) 往前第一个位置,其值小于 \(a_i\),\(l_2\) 表示 \(i\) 往后第一个位置,其值大于 \(a_i\),\(r_2\) 表示 \(i\) 往后第一个位置,其值小于 \(a_i\)。

则该区间的左端点可取 \([l_1 - 1, r_1]\),右端点可取 \([l_2, r_2 + 1]\)。总共有 \((r_1 - l_1) \times (r_2 - l_2)\) 种取法,用总贡献减去即可。

Div. 3 F. Kirill and Mushrooms

按 \(p_i\) 顺序倒序枚举选了多少个数可以规避掉 \(p_1 \sim p_k \to 0\) 的这个限制。用小根堆维护当前最小值。每次往左移动时需要确保堆内元素数量不超过当前枚举的 \(i\)。每次弹掉堆顶可以确保最小元素最大。相当于是维护后缀的第 \(i\) 大值。

Div. 2 D. XOR Construction

\(由 b_i \oplus b_{i + 1} = a_i\) 知:

\[\bigoplus_{i = 1} ^ k a_i = b_1 \oplus b_{k + 1} \]

移项知:

\[b_1 \oplus (\bigoplus_{i = 1} ^ k a_i) = b_{k + 1} \]

所以如果确定了 \(b_1\),则其它的 \(b_i\) 也是唯一确定的了。

令 \(pre_i = \bigoplus_{i = 1} ^ k a_i\),题目保证有解则 \(pre_i\) 互不相同且 \(pre_i\) 最高位要小于等于 \(n - 1\) 的最高位。那么我们可以枚举 \(b_1\) 的取值,只需判断 \(\max_{i = 1} ^ {n - 1} pre_i \oplus b_1\) 是否小于 \(n\) 即可。这个可以挂在 01 Trie 上解决。

Div. 2 D. Blocking Elements

答案要求“最大值最小”,我们可以联想到二分答案。设 \(dp_i\) 为钦定选 \(a_i\) 封锁的最小值。设 \(pre_i\) 为前缀和数组,\(x\) 为当前二分的最大答案。则有转移:

\[dp_i = \min_{j \in [1, i - 1] \land pre_{i - 1} - pre_j \le x} \{ dp_j \} + a_i \]

由于 \(a_i > 0\),则 \(pre_i\) 单调递增。则 \(j\) 的决策区间随 \(i\) 的增大而向右滑动。可以用双指针或者单调队列优化转移。

Div. 2 F. Orangutan Approved Subarrays

稍微分析可知,只有出现以下情况无解:

设 \(x, y\) 为两个值不同的元素,它们在序列上的排列顺序形如 \(x, y, x, y\)。

我们考虑对于每一个右端点去找到一个最小的左端点满足这一段区间合法。设这个最小的左端点为 \(res_i\)。则显然 \(res_i\) 不降。记位置 \(i\) 的元素上一次出现的位置为 \(pre_i\),下一次出现的位置为 \(nxt_i\),则 \(res_i\) 可以形式化定义为:

对于一个位置 \(i\) 而言,令 \(j \in [1, pre_i - 1]\) 满足 \(nxt_j \in [pre_i + 1, i - 1]\) 的 \(j\) 的集合为 \(S\)。则 \(res_i = \max \{ res_{i - 1}, (\max_{k \in S} k) + 1 \}\)。

那么 \(res_i\) 就好求了,在枚举到 \(i\) 时将 \(pre_i\) 插入线段树,每次在线段树上二分出在 \([1, pre_i - 1]\) 中大于 \(pre_i\) 的最大位置即可。

Div. 2 F. Large Graph

由于 \(k \geq 2\),那么有一个显然的观察是矩阵的对角线是必然联通的。那么我们可以直接对于矩阵的 \(2n - 1\) 条对角线进行考察。至于对角线之间的距离,可以以主对角线为界分为上半矩阵和下半矩阵。可以优先处理上半矩阵的对角线距离,这个是好做的,按照第一行位置可以找到距离关系。而下半矩阵对角线对应的上半矩阵对角线的相对距离一定为 \(n\),则下半距离的距离关系也确定好了。这种距离关系可以转化为编号关系。即对于一个 \(a_i(i \geq 2)\) 来说,其对应的编号为 \(i - 1\) 和 \(i + n - 1\)。特殊地,\(a_1\) 对应的编号为 \(n\)。

经过此转化后,题目转化为:给定一个序列 \(a\),对于位置 \(i\) 可以选择位置 \(j \in [i + 1, i + k]\)。若 \(\gcd(a_i, a_j) > 1\) 则 \(i \to j\) 连边。问有多少个连通块

考虑对 \(a_i\) 最小质因数分解,将位置 \(i\) 挂在它的所有质因数上。令 \(S_x\) 表示一个质因数 \(x\) 上面挂的位置集合。再枚举每个质因数 \(x\),若 \(i, j \in S_x, |i - j| \le j\) 则可以在并查集上合并 \(i, j\)。最后并查集的连通块数量即为答案。

具体实现的话,只需对每个 \(S_x\) 排序,每次对 \(S_x\) 的相邻两项考察是否能合并即可。

对于 \(a_i = 1\) 的部分是不可能连通的,特殊处理一下即可。

Global Round E. Shuffle

考虑把构建新树的过程当作每次对于每个连通块删掉一个点,那一个点在新树中能被作为叶子的条件是他的邻居在他之前被删掉了。那么这是一个最大独立集模型,可以换根进行处理。需要注意一个 corner case 是若一个点只连接了一条边,那么可以先把它当成叶子删去而后对剩下的结构考虑。

Div. 1 B2. Painting the Array II

简要题意

你可以将序列 \(a\) 划分为两个新序列,问两个新序列的颜色段数量总和最小值。

思路

考虑维护两个队列表示这两个序列,设其分别为 \(q_1, q_2\)。考察一个数 \(a_i\) 能否被插入至 \(q_1\)。(\(q_2\) 和 \(q_1\) 相反所以只讨论 \(q_1\))

记 \(q_1\) 队尾元素为 \(x\),\(q_2\) 末尾元素为 \(y\),\(nxt_i\) 表示 \(a_i\) 在 \(i\) 之后第一次出现的位置。若 \(a_i = x\) 则将 \(i\) 插入 \(q_1\)。否则若 \(nxt_x > nxt_y\) 则将 \(i\) 插入 \(q_1\)(感性理解是 \(q_1\) 向后匹配到一个相同的字符的可能性更大),否则将 \(i\) 插入 \(q_2\)。

ICPC D. Digits

思路

dp 是简单的,但是会爆精度。一个小 trick 是 \(a_i \to \log a_i\)。

Технокубок E. Skyline Photo

思路

划分序列的题目第一时间想到 dp。设 \(dp_i\) 表示以 \(i\) 为结尾的最大价值,有转移:

\[dp_i = \max_{j = 1} ^ {i - 1} \{ dp_{j - 1} + b_{\operatorname{argmin}_{k \in [j, i]} \{ h_k \}} \} \]

\(\operatorname{argmin}\) 表示使得该值最小的参数。

这个 \(\operatorname{argmin}\) 很反直觉,于是我们不直接维护这个,转而我们思考题目本质。相当于我们钦定了一个最小值算其贡献,那么可以维护一个单调栈,弹栈进栈对应贡献的增删。栈顶元素一定是某个区间的最小值。那么只需要区间加,区间查询 \(\max\)。线段树轻松胜任。

Div. 2 E. XOR Tree

简要题意

给定一棵树,树上点有点权。你可以将一个点的点权更改为 \([1, 2 ^ {30}]\) 的数。问最少更改多少次使得树上不存在异或和为 \(0\) 的路径。

思路

考虑弱化问题,假设我们只需要对一棵子树的所有经过根的路径判断怎么做。首先这个问题可以划分为若干子问题,即在讨论当前节点的时候其儿子的答案是确定的。那么可以对于子树内每一个节点维护其到根的距离集合,在合并一个儿子的时候判断两个集合是否有相同元素即可。

  • 若存在非法路径,则改根一定最优。

证明:首先不改根转而改其它点显然是不优的,因为根以外的节点影响的范围严格包含于根影响的范围。然后是改根一定可以使得不存在经过根的非法路径。因为路径条数至多 \(O(n ^ 2)\),从而路径疑异或和数量至多 \(O(n ^ 2)\)。而 \(n ^ 2 \le 10 ^ {10} \le 2 ^ {30} = V\),因此得证。

ICPC L. Longest Array Deconstruction

简要题意

给定序列 \(a\),选择一个子序列 \(b\) 使得 \(\sum_{i = 1} ^ n [b_i = i]\) 最大。

思路

设 \(dp_i\) 表示前 \(i\) 个数且 \(a_i\) 有贡献的最大价值。那这是一个子序列转移形式,转移形如 \(dp_i = \max \{ dp_j + 1 \}\)。

对于这个转移而言,首先 \(a_j < a_i\)。其次由于把 \(a_i\) 移到 \(a_i\) 位置上需要删 \(i - a_i\) 个数,把 \(a_j\) 移到 \(a_j\) 位置上需要删 \(j - a_j\) 个数,而 \(a_j\) 在 \(a_i\) 前面,因此在 \(a_j\) 前面删的数必然会算进 \(a_i\) 前面删的数目里面。因此必须要有 \(j - a_j \leq i - a_i\)。整理两个条件也能得到 \(j < i\)。因此这是一个经典的二维偏序形式,排序一维 ds 维护一维即可。

Div. 3 F. Red-Black Number

思路

设 \(dp_{i, x, y, k}\) 表示填了前 \(i\) 位,红色数字模 \(A\) 的取值,黑色数字模 \(B\) 的取值,选了 \(k\) 个红色数字是否可取。转移是好写的。

Div. 2 E. Staircases

思路

设 \(dp_{i, j, k}\) 表示以点 \((i, j)\) 为终点,上一步往右还是往上的阶梯个数。那么对一个点的状态进行更改,可能影响的格子是在右下角固定的,可以 \(O(n + m)\) 更改 dp 值。同时记录答案的偏移量即可。总时间复杂度 \(O(Q(n + m))\)。

CF1614D1 Divan and Kostomuksha (easy version)

简要题意

给定序列 \(a\),你可以重排 \(a\),最大化下面式子:

\[\sum_{i = 1} ^ n \gcd_{j = 1} ^ i a_j \]

思路

设计 \(dp_i\) 表示当前 \(\gcd = i\) 的最大价值。那么上一个 \(\gcd\) 一定是 \(i\) 的倍数。记 \(f_i\) 表示序列中有多少为 \(i\) 的倍数的元素,则有转移:

\[dp_i = \max_{i \mid j} \{ dp_j + i \times (f_i - f_j) \} \]

瓶颈在于倍数法枚举,时间复杂度 \(O(n \ln n)\)。

Div. 2 D. Chopping Carrots

简要题意

给定序列 \(a\),构造一个序列 \(p\),满足 \(\forall i \in [1, n], p_i \le k\)。在此前提下,最小化:

\[\max_{i = 1} ^ n \{ \lfloor \frac{a_i}{p_i} \rfloor \} - \min_{i = 1} ^ n \{ \lfloor \frac{a_i}{p_i} \rfloor \} \]

D1 思路

直接枚举 \(\min \max\) 取值。

D2 思路

记 \(\lfloor \frac{a_i}{p_i} \rfloor\) 为 \(b_i\)。先令 \(p_i\) 全部为 \(k\)。那么这样我们每次实际上是想扩展 \(b_i \to b_i + 1\) 是否能使得答案更优。所以我们可以用优先队列维护当前的最小值,每次拿这个最小值扩展一定是最优的,它可以使得最大值尽可能小。每次弹出队头时更新答案即可。\(b_i\) 的取值至多 \(O(\sqrt n)\) 种,因此其至多被扩展 \(O(\sqrt n)\) 次。时间复杂度 \(O(n \sqrt n \log n)\)。

Div. 2 E. Cross Swapping

简要题意

给定一个方阵 \(A\),可以任意次数交换一行一列,求操作后字典序最小的方阵。

思路

将行列之间的交换拆分成两个单点之间的交换。则 \(A_{i, j}\) 只能和 \(A_{j, i}\) 交换。由于要求字典序最小,因此我们按 \((1, 1) \to (n, n)\) 顺序去考虑问题。不难发现只需要对于每一行(或列)维护一个扩展域并查集判断其是否能交换 \(i, j\) 即可。

Div. 2 E. Long Way Home

简要题意

给定 \(n\) 个点 \(m\) 条边一张无向带权图,此外每个点还与其余 \(n - 1\) 个点连了边,我们称这些边为魔法边。魔法边中,\(i \to j\) 这条边的权值是 \((i - j) ^ 2\)。你可以至多走 \(k(k \le 20)\) 条魔法边,问点 \(1\) 到其它所有点的最短路。

思路

设 \(dis_i\) 表示 \(1 \rightsquigarrow i\) 的最短路。假设我们只能走 \(1\) 条魔法边。那么对于任意的 \(dis_i\),都有更新:

\[dis_i = \min_{j = 1} ^ n \{ dis_j + (i - j) ^ 2 \} \]

这个东西可以拆掉平方,粗略的式子如下:

\[dis_i = \min \{ dis_j + j ^ 2 - 2 \times i \times j + i ^ 2 \} \]

相当于插入一条 \(y = -2 j x + j ^ 2\) 的直线,在 \(x = i\) 处查询所有直线的最小值。这是李超线段树所擅长的。

至于从走 \(1\) 条魔法边到走 \(k\) 条魔法边这个问题的强化,你可以每次更新完 \(dis\) 之后在放进 dijkstra 中松弛。总时间复杂度 \(O(k(n + m) (\log n + \log m))\)。

Div. 2 D2. Xor-Subsequence (hard version)

简要题意

给定序列 \(a\),求出最长的子序列,使得子序列中 \(\forall j < i, a_j \oplus i < a_i \oplus j\)。

思路

这是一个经典的子序列 dp 模型。有转移:

\[dp_i = \max_{j < i \land a_j \oplus i < a_i \oplus j} \{ dp_j + 1 \} \]

这是 \(O(n ^ 2)\) 的。对于转移的限制条件,考虑拆位从高到低考虑。若在某一位上 \(a_j \oplus i = a_i \oplus j\) 等价于 \(a_j \oplus j = a_i \oplus i\)。把 \(a_i \oplus i\) 插入 01 Trie 中,每次走与其相同的一条链,反向统计答案即可。

ICPC L. Lemper Cooking Competition

简要题意

给定序列 \(a\),可以进行若干次操作。一个操作 \(i\) 是将 \(a_{i - 1} \to a_{i - 1} + a_i, a_{i + 1} \to a_{i + 1} + a_i, a_i \to -a_i\)。问最少操作多少次可以使得 \(a\) 非负或报告无解。

思路

注意到序列总和是不变的,不妨从其前缀和入手。那么接下来的操作就很明了了,每次操作相当于交换两个相邻的前缀和。要使得序列非负相当于要通过交换若干相邻的前缀和使得前缀和不降。这个是冒泡排序的经典结论,答案为逆序对总数。

另外第 \(n\) 个前缀和是不能移动的。若有 \(pre_i > pre_n\) 则无解。由于我们只是将前缀和重排而没有更改,所以若存在 \(pre_i < 0\) 也无解。

Div. 2 C2. Good Subarrays (Hard Version)

简要题意

一段区间 \([l, r]\) 合法当且仅当 \(\forall i \in [l, r], a_i \geq i - l + 1\)。问有多少段合法区间。

思路

对于 \(a_i\) 而言,能包含它的区间的最小左端点为 \(\max \{ 1, i - a_i + 1 \}\)。记为 \(b_i\)。我们钦定 \(a_i\) 为右端点,则其合法的最小左端点为 \(\max_{j = 1} ^ i b_i\)。记其为 \(c_i\)。那么最后的答案是 \(\binom{n}{2} - \sum_{i = 1} ^ n (c_i - 1)\)。

考虑用线段树维护 \(c\)。\(c\) 的本质是 \(b\) 的前缀最大值,单点是可以轻松维护的。关键在于维护 \(\sum c_i\)。不难发现 \(c\) 是单调不降的。因此在线段树的区间上,左儿子的贡献不变。右儿子有可能会横跨中点参与左儿子的贡献。那么只需要进行一个类似单侧递归的操作即可。

Div. 2 E. FTL

思路

设 \(f_i\) 表示通过若干次单发,而后最后一次是双炮连发的使得飞船损耗耐久度为 \(i\) 所需的最小时间。额外设计 \(dp_i\) 表示经过若干次单双发混用使得飞船损耗耐久度为 \(i\) 所需的最小时间。则有转移:

\[f_{i} = \min_{j = 0} ^ {j \times (p_1 - s) + (p_1 + p_2 - s) \le i} \{ \max \{ t_1 \times (j + 1), t_2 \times \lceil \frac{i - (j \times (p_1 - s)) + (p_1 + p_2 - s)}{p_2 - s} \rceil + 1 \} \} \]

\[dp_i = \min_{j = 0} ^ {i - 1} \{ dp_j + f_{i - j} \} \]

答案是 \(\min dp_i\)。

Div. 1 + Div. 2 E. Routing

简要题意

给你一张图,你需要在这张图上剥离一棵基环树,使得每个点到基环树环上的距离不超过 \(1\)。

思路

由于 \(n \le 20\),我们可以往 \(O(2 ^ n)\) 算法上去想。一个平凡的想法是,枚举环上的点集。在确定了环的点集之后,我们只需要判断不在环上的点是否与环上的某个点直接相连即可。

那么接下来可以状压枚举一个点集,而后判断该点集是否能成环即可。

考虑状态转移:点集 \(S \to S \cup \{ x \}\),若存在两点 \(i, j \in S(i \not = j)\) 满足边 \((i, x)\) 和 \((j, x)\) 都存在,则该转移合法。时间复杂度 \(O(n ^ 3 2 ^ n)\)。

不妨断环成链,设计 \(dp_{S, x}\) 表示是否存在以点集 \(S\) 中最小编号的点为起点,且由 \(S\) 构成的链,再走恰好一步能到达点 \(x\)。转移是显然的。

在这个状态定义下,若点 \(x\) 与点集 \(S\) 中最小编号的点直接相连,则该状态构成环。

至于输出方案,记录该状态由哪个状态转移而来即可。

我们需要枚举点集,上一个到达的点和将要到达的点,时间复杂度 \(O(2 ^ n n ^2)\)。

还有一种更天才的状态设计可以把复杂度降为 \(O(2 ^ n n)\)。由于我想不到所以不再赘述。

Div. 1 + Div. 2 E. Bracket Cost

简要题意

给定一个括号序列。你可以将一个括号序列循环右移一位或者在某个位置插入一个左括号或右括号,将这个记为一次操作。定义 \(f(l, r)\) 表示将序列的区间 \([l, r]\) 变成合法括号序列的最少操作次数。求:

\[\sum_{i = 1} ^ n \sum_{j = i} ^ n f(i, j) \]

思路

  • 记某序列的左括号数量为 \(L\),右括号数量为 \(R\),已匹配的括号数量为 \(X\),可以构造出经过 \(\max \{ L, R \} - X\) 次操作后使得该序列成为合法括号序列,且该操作最优。

证明:依次考虑每一个左括号,如果有未匹配的右括号,则这些右括号在此左括号前面。可以直接把左括号转到某一个右括号前面。否则在该左括号右边加一个右括号。(若依次考虑右括号同理)不难发现,每次操作至多减少一个失配括号,则该构造最优。

那么我们直接计算 \(\sum \max \{ L, R \} - X\) 即可。

对于 \(\sum X\),记一对匹配括号的位置为 \(l, r\),则这一对括号的贡献是 \(-l \times (n - r + 1)\)。

对于 \(\sum \max \{ L, R \}\),可以将其变形为 \(\sum L + R - |L - R|\)。\(\sum L + R = \sum_{i = 1} ^ n i \times (n - i + 1)\)。将左右括号 \(1, -1\) 赋值,则 \(\sum |L - R|\) 相当于求所有区间和的绝对值的和。这个可以将前缀和数组排序后只需要算 \(\sum_{i = 1} ^ n \sum_{j = i + 1} ^ n pre_j - pre_i\),枚举一维预处理一维即可。

Div. 1 + Div. 2 F. Magician and Pigs

咕一下,因为我似乎没怎么搞懂。

Div. 2 E. Labeling the Tree with Distances

简要题意

给定一棵树和一个序列 \(a\)。设 \(dis(x, y)\) 表示点 \(x, y\) 在树上的距离。对于一个节点 \(i\),若 \(\forall j \in [1, n](j \not = i), a_j = dis(i, j)\),则称点 \(i\) 为好节点。问点 \(1 \sim n\) 中哪些是好节点。

思路

可以使用集合哈希表示以某个点为根时的 \(dis\) 集合,而后换根即可。

Div. 2 F. Blocking Chips

简要题意

给定一棵树。有 \(k\) 个棋子放在给定位置上,这些位置初始被染成黑色。你可以进行若干次操作,每次操作可以将第 \((i - 1) \bmod k + 1\) 个棋子从当前点移动到一个相邻的白点,并将该点染黑。若当前局面不能移动则结束。问最多能进行多少次操作。

思路

首先,题目所需的操作顺序实际上只是限制每个棋子的移动步数。而后我们考虑怎么判断操作 \(k\) 次是否是合法。一个比较显然的贪心是,对于一个棋子所在的节点 \(x\),如果它还能继续往下走则往下走,否则往上走。可以感性理解为一个节点的后代影响比其祖先更小。对于第一种情况,维护 \(dis_i\) 表示点 \(i\) 到其子树内的白点的最长距离,对于第二种情况可以直接扩展。然后操作次数是单调的,因此可以直接二分答案。

Div. 2 E. Walk the Runway

咕一下,因为我似乎没怎么搞懂。

P1333 瑞瑞的木棍

思路

将一根木棍看成一条无向边,判断其是否存在欧拉路径即可。

P2731 [USACO3.3] 骑马修栅栏 Riding the Fences

简要题意

构造一个无向图的字典序最小的欧拉回路。

思路

对于每个点的出边按其对应点的大小排序。在此基础上再用 Hierholzer 构造可以保证字典序最小。

ABC - G - Unique Walk

简要题意

给定一张无向图和一个边集 \(S\),判断是否存在一条路径使得 \(S\) 中的边恰好出现一次。

思路

将 \(S\) 中的边成为必需边,其余边称为非必需边。将所有非必需边所连成的点缩成一个点,而后对于这张新图跑欧拉路径即可。

P7771 【模板】欧拉路径

模板题。

P1127 词链

简要题意

如果单词 \(X\) 的末字母与单词 \(Y\) 的首字母相同,则 \(X\) 与 \(Y\) 可以相连成词链,请你找到字典序最小的词链,使得每个单词在词链中出现且仅出现一次。

思路

将字母看成点,单词看成边。对于每个点的出边的点按其单词字典序排序后求其欧拉路径即可。

P3520 [POI 2011] SMI-Garbage

简要题意

给定一张无向图,你必须经过一些边奇数次,经过其余边偶数次。构造一些简单环使得其满足上述条件。

思路

欧拉路径(回路)有经典结论:存在一个方案经过这条边偶数次,就存在方案不经过这条边;存在一个方案经过这条边奇数次,就存在方案经过这条边。

因此只需要将原图的欧拉回路集合拆分成若干个简单环即可。可以用类似于求 SCC 的方法维护一个栈。

Div. 2 D. Turtle and Multiplication

简要题意

构造一个序列 \(a\),使得 \(\forall i, j(i \not = j)\) 满足 \(a_i \times a_{i + 1} \not = a_j \not = a_{j + 1}\)。

思路

不妨将 \(a_i\) 视为质数,这样原限制转化为判定两个二元组 \((a_i, a_{i + 1}), (a_j, a_{j + 1})\) 是否相同。这样就可以 \(a_i \to a_{i + 1}\) 建边,那么问题变成找到点数最少的带自环的完全图,使得这个完全图存在一条经过 \(n − 1\) 条边且不经过重复边的路径。

设这个图的点数为 \(k\),则 \(k\) 为奇数时所有点度数为偶数,是一张欧拉图,构造路径是 easy 的。若 \(k\) 为偶数,则可以删去 \((2 \times x, 2 \times x + 1)\) 这一类边使得该图变为欧拉图。继续使用 Hierholzer 构造即可。

\(k\) 是 \(O(\sqrt n)\) 级别的,可以直接循环求出。

Div. 1 B. Weird journey

简要题意

给定一张无向图,你可以选择 \(m - 2\) 条边经过 \(2\) 次,其他 \(2\) 条边经过 \(1\) 次。问有多少种方案。

思路

转化为 \(2 \times m\) 条边,可以删掉两条边。问新图存在欧拉路径的删边方案。

可以删一条边一个自环、两个自环或两条共一个顶点的边。记自环个数为 \(x\),点 \(i\) 度数为 \(deg_i\)。答案即为:

\[\binom{x}{2} + x \times (m - x) + \sum_{i = 1} ^ n \binom{deg_i}{2} \]

Div. 2 E. One-Way Reform

简要题意

将一张无向图定向,最大化出度等于入度的点。

思路

  • 答案为原图度数为偶数的点。

证明:必要性:显然若出度等于入度则原图度数一定为偶数。充分性:考虑一个构造,不妨将所有度数为奇数的点跟一个虚点连接,那么度数为奇数的点都转化为度数为偶数的点。即该图存在欧拉回路,按照欧拉回路的方式给边定向即可。

实际实现也是把这个虚点建出来,Hierholzer 构造即可,只需要保留不包含虚点的边。

Div. 2 E. Maximum Matching

简要题意

给定四个点的无向图,在上面找一条权值最大的路径。

思路

若图不连通,那么连通块大小只能是 \(1, 2, 3\),很好证明连通块内度数为奇数的点的个数不超过两个。那这个连通块一定是欧拉图,所得的最大值就是连通块内边权和。

若图连通,那么只有四个点的度数全部为奇数的图不是欧拉图。于是你可以删掉一条非自环边,这样可以使得某两个点的度数减 \(1\) 或者将其分割为多个连通块。这都会使得图变成一个欧拉图。

那么我们只需要枚举断哪一条边即可。

keyence E - Connecting Cities

简要题意

给定一张图、序列 \(a\) 和定值 \(D\)。一条边 \(i \to j\) 的权值为 \(|i - j| \times D + a_i + a_j\)。求该图的最小生成树。

思路

可以使用分类讨论去掉绝对值,于是我们只做 \(i < j\) 的讨论,\(i > j\) 是类似的。

对于完全图的最小生成树,考虑 boruvka。于是我们只需要找到每个连通块的最优势出边即可。

当 \(i < j\) 时,上述式子可以化为:\(a_i - i \times D + a_j + j \times D\)。假设我们枚举 \(i\),那么答案就是不在点 \(i\) 连通块里的点 \(j\) 的 \(a_j + j\) 的最小值。这个我们可以维护后缀(\(i > j\) 则是前缀)的所属连通块不同的最小、次小值。每次合并最优势出边的两端点即可。

P11307 [COTS 2016] 建造费 Pristojba

简要题意

给定一张图和序列 \(a\),边 \(i \to j\) 的权值是 \(a_i + a_j\)。现有 \(m\) 种无向边 \(x \to [l, r]\),求该图的最小生成树。

思路

那么对于点连向区间,可以在线段树上维护 \([l, r]\) 的 \(a_i\) 所属连通块不同的最小、次小值,只需要判断 \([l, r]\) 的最小次小值哪个和 \(x\) 不在一个连通块即可。

对于区间连向点,对于每一个点 \(i \in [l, r]\) 维护其可达的所属连通块不同最小、次小值即可。对于 \([l, r] \to x\),令当前最小(或次小值)为 \(t_i\),只需对每个 \(i \in [l, r]\) 执行 \(t_i \to \min \{ t_i, a_x \}\) 即可(更新最小值则将原信息传给次小值)。由于只需要区间修改、单点查询,于是可以用类似于标记永久化的思想,每次查询时求答案即可。

P1993 小 K 的农场

思路

对于 \(x_i = x_j + c_k\) 的建图手法:转化为 \(x_i \le x_j + c_k\) 和 \(x_j \le x_i - c_k\)。

P2294 [HNOI2005] 狡猾的商人

思路

转化为前缀和。

P4926 [1007] 倍杀测量者

简要题意

给出不等式组,每个不等式形如:

\[x_a \ge (k_i - t) \times x_b \]

\[(k_i + t) \times x_a > x_b \]

求出最大的 \(t\) 使得不等式无解。

思路

乘法不等式的经典手法是取对数,不妨只对第一类不等式考虑,则该不等式转化为:

\[\log x_a \ge \log(k_i - t) + \log x_b \]

由于 \(\log\) 的单调性和差分约束只会约束上界或者下界,所以 \(t\) 是具有单调性的,可以二分答案。

ABC - G - Specified Range Sums

思路

依旧是刻画到前缀和上,对于正整数这一限制,额外约束 \(x_i - x_{i - 1} \ge 1\) 即可。因为要求最小序列和,因此转化为上界约束跑最短路即可。

P4878 [USACO05DEC] Layout G

思路

同样的转化为上界约束跑最短路。

可以跑两次 SPFA,第一次判无解,第二次求答案即可。

P3530 [POI 2012] FES-Festival

简要题意

给定不等式组,每个不等式形如:

\[x_a = x_b + 1 \]

\[x_a \le x_b \]

求 \(x\) 的所有解中出现过的数字有多少个。

思路

依然把等式拆分成不等式进行上界约束,可以 \(a \to b\) 边权为 \(-1\),\(b \to a\) 边权为 \(1\) 建边。

那么出现负环则无解,考虑用 Floyd 求最短路。记 \(dis_{i, j}\) 表示 \(i \rightsquigarrow j\) 的最短路。出现负环当且仅当 \(dis_{i, i} < 0\)。

同时因为是上界约束,有:\(x_i - x_j \le dis_{i, j}\)。

考虑一个 SCC \(S\)。记 \(D = \max_{i, j \in S} dis_{i, j}\)。

  • \(S\) 中的答案为 \(D + 1\)。

证明:令 \(S\) 中最小最大的点为 \(u, v\),则:\(x_u - x_v \le dis_{u, v} \le D\)。由于 \(x_i\) 为整数,因此答案上界是 \(D + 1\)。选择满足 \(dis_{s, t} = D\) 的点对 \((s, t)\),给 \(S\) 中每个点 \(u\) 赋值 \(x_u \to dis_{s, u}\)。则该构造一定合法并且 \(x_s = 0, x_t = D\)。由于图上的边权集合为 \(\{ 0, 1, -1 \}\),因此 \(0 \sim D\) 中每一个值都能被选中。

  • 答案为各个 SCC 中的答案之和。

证明:缩点后得到一个 DAG。并且,SCC 之间只可能存在权值为 \(0\) 的边,因为其它边对应双向边,两端点一定同属一个 SCC。一个 SCC 内的变量全部加上同一个数还会是一组合法解,因此按拓扑序对于每个 SCC 的所有变量赋值一定可以构造一组解使得各个 SCC 的答案无交。

记 \(S\) 为一个强连通分量,\(G\) 为原图,则答案为:

\[\sum_{S \subseteq G} \max_{u, v \in S} \{dis_{u, v} + 1\} \]

P4180 [BJWC2010] 严格次小生成树

思路

在最小生成树上维护 \(\max\) 的同时维护 \(\operatorname{second} \max\) 表示与 \(\max\) 值不相同的最大值即可。

Div. 2 E. Minimum spanning tree for each edge

思路

对于每一条边 \((u, v, w)\),讨论其是否在最小生成树上。记最小生成树权值和为 \(M\)。

  • 树边:

答案为 \(M\)。

  • 非树边:

记 \(k\) 为路径 \(u \rightsquigarrow v\) 上的权值最大值。答案为 \(M - k + w\)。

P1967 [NOIP 2013 提高组] 货车运输

思路

建出 kruskal 重构树,跳 LCA 即可。

P2245 星际导航

和上题一样。

P4197 Peaks

思路

对于路径权值的限制,用 kruskal 重构树解决;对于可达第 \(k\) 小,按深度建可持久化线段树即可。

Div. 2 E. Qpwoeirut and Vertices

思路

经典结论:

\[\displaystyle \operatorname*{LCA}_{i = l} ^ r i = \operatorname{LCA}(\operatorname*{avgmin}_{i = l} ^ r dfn_i, \operatorname*{avgmax}_{i = l} ^ r dfn_i) \]

因此把一个区间查询转化为了两个单点查询。跳 LCA 即可。

AGC D - Stamp Rally

思路

二分答案,而后分别把两个点倍增即可。

P4768 [NOI2018] 归程

思路

同样是用 kruskal 重构树解决边权限制和强制在线。那么接下来只要考虑一件事:怎样在重构树上点权不超过 \(k\) 的点的子树里求到 \(1\) 号点的最短路。

在原图上跑最短路,由于 kruskal 重构树的单调性,我们只需要倍增求答案即可。

P4899 [IOI 2018] werewolf 狼人

简要题意

给定一个无向图,每次给出询问 \((s, t, l, r)\),问是否存在一条起点为 \(s\),终点为 \(t\) 的路径满足先经过大于等于 \(l\) 的点再经过小于等于 \(r\) 的点。

思路

先拆点,这样可以将点权转化为边权。那么这样很符合 kruskal 重构树的形式。那么可以建出一个最小重构树和最大重构树。对这两棵树分别跳到 \(l, r\) 的位置,问题转化为这两棵子树的叶子节点是否有交。

叶子的交集本质上是子树的交集。因此可以用 dfs 序刻画。记一个点在两棵树上的 dfs 序是 \((x, y)\),那么答案合法则要求 \(x \in [l_1, r_1], y \in [l_2, r_2]\)。这是一个二维数点的形式,离线下来即可。

P3684 [CERC2016] 机棚障碍 Hangar Hurdles

简要题意

你正在评估一些关于一个巨型飞机仓库的建设计划。飞机仓库的地面可以表示为 \(n\) 行 \(n\) 列的网格图,其中每个格子要么是空的,要么有障碍物。行从上到下依次被编号为 \(1\) 到 \(n\),列从左到右依次被编号为 \(1\) 到 \(n\)。

存放飞机零件的大型集装箱能在飞机仓库的地面上自由移动是很重要的。我们可以将每个集装箱看作一个以某个格子为中心的边平行于坐标轴的正方形。对于一个奇数 \(k\),一个尺寸为 \(k\) 的集装箱是一个包含 \(k\) 行 \(k\) 列的正方形。一个集装箱的坐标为其中心格子的坐标。集装箱可以向上下左右移动,但不能碰到障碍物,且不能移出仓库的边界。

给定 \(q\) 对格子 \(A_k\) 和 \(B_k\),对于每对格子,请找到能从 \(A_k\) 移动到 \(B_k\) 的集装箱的最大尺寸,注意这个尺寸也要是一个奇数。

思路

首先把每个点点权赋为以该点为中心的集装箱最大尺寸,然后每个点向四周连边,建 kruskal 重构树。找两个点的 LCA 即可。

至于如何找集装箱的最大尺寸,直接二分 + 前缀和 check 即可。

Div. 2 G. Clusterization Counting

思路

先建出 kruskal 重构树,设 \(dp_{x, i}\) 表示将 \(x\) 子树划分为 \(i\) 个连通块的方案数。这是一个树上背包的形式,转移为:

\[dp_{x, i + j} = \sum_{i = 1} ^ {ls_x} \sum_{j = 1} ^ {rs_x} dp_{ls_x, i} \times dp_{rs_x, j} \]

注意特判该子树是否能够构成完全图。上下界优化可以 \(O(n ^ 2)\)。

P2146 [NOI2015] 软件包管理器

思路

阅读理解题。题意可以转化为链改、链查和子树查。

P2486 [SDOI2011] 染色

简要题意

链推平,链查询颜色段数。

思路

线段树上记录区间的颜色段数,那么我们需要维护 \(lc, rc, res\) 表示线段树上区间的左端点颜色、右端点颜色和颜色段数。这样是好合并的。对于链查询,可以维护左链和右链信息,其合并方法是类似于线段树上的信息合并的。

P3976 [TJOI2015] 旅游

简要题意

记路径 \(u \rightsquigarrow v\) 对应的点的序列是 \(\{p_i\}_{i = 1} ^ k\),多次询问:

\[\max_{i = 2} ^ {k - 1} \{ \max_{j = 1} ^ i w_{p_j} - \min_{j = i + 1} ^ k w_{p_j} \} \]

此外还有链修改。

思路

对于每个区间都维护答案信息,则在线段树上需要维护 \(mn, mx, res\) 表示线段树上区间的最小、最大值和从左到右的答案。但是这样会有问题,设有路径 \(u \rightsquigarrow v\),点 \(u, v\) 的 LCA 为 \(k\),则 \(u \rightsquigarrow k\) 和 \(v \rightsquigarrow k\) 的其中一个路径是向下的。这里向下的定义是路径指向深度增大的方向(向上同理)。于是为了信息的完备性,我们需要额外维护 \(Res\) 表示线段树上区间从右往左的答案。这样我们查询一个向上的子路径时使用 \(res\) 信息,向下的子路径使用 \(Res\) 信息即可。

P4116 Qtree3

简要题意

单点修改,查询 \(1 \rightsquigarrow u\) 第一个非 \(0\) 位置。

思路

考虑直接以 \(1\) 为根,这样只需要 \(u\) 一直向上跳。那么对于只需要每一次跳到链顶时找到这一段里面 dfs 序最小的非 \(0\) 位置,可以在区间上线段树二分。

P5343 【XR-1】分块

思路

设 \(dp_i\) 表示长度为 \(i\) 时的答案。则有转移:

\[dp_i = \sum_{x \in S} dp_{i - x} \]

由于 \(x_{max} \le 100\),可以考虑矩阵加速。

套路地,我们构造一个 \(100 \times 100\) 的转移矩阵 \(A\),对于每一行 \(i\),将 \(S\) 中出现的元素 \(x\),\(A_{i, x} \to 1\),矩阵的其余元素赋为 \(0\)。

P10502 Matrix Power Series

简要题意

给定方阵 \(A\) 和整数 \(k\),求:

\[\sum_{i = 1} ^ k A ^ i \]

思路

考虑分治,记 \(f(k) = \sum_{i = 1} ^ k A ^ i\),\(x = \lfloor \frac{k}{2} \rfloor\)。

  • \(2 \mid k\):

\[f(k) = f(x) + A ^ x f(x) \]

  • \(2 \nmid k\)

\[f(k) = f(x) + A ^ x f(x) + A ^ k \]

这样时间复杂度是形如 \(T(n) = T(\frac{n}{2}) + O(k ^ 3 \log n)\) 的,于是总时间复杂度 \(O(k ^ 3 \log ^ 2 n)\)。

P10503 233 Matrix

思路

重要转移:

\[a_{i, j} = 10 \times a_{i - 1, 1} + 3 + \sum_{k = 2} ^ j a_{i - 1, k} \]

于是直接把每一列的 \(a\) 放到答案向量里即可矩阵加速。

CSES 1723

模板。

P3758 [TJOI2017] 可乐

思路

可以新建一个点表示自爆,且该点只存在一条指向自己的出边。

P2151 [SDOI2009] HH 去散步

思路

将无向边拆成正反两条边,对于每一条边记录其可以走到的边集即可,需要排除掉该边的反向边。

P4159 [SCOI2009] 迷路

思路

拆点。

CSES 1724

模板。

P4910 帕秋莉的手环

简要题意

可以在一个环上黑白染色,要求不存在相邻白色的方案数。

思路

设 \(dp_{i, 0 / 1}\) 表示前 \(i\) 位且第 \(i\) 位染黑或白的方案数。

转移:

\[dp_{i, 0} = dp_{i - 1, 1} \]

\[dp_{i, 1} = dp_{i - 1, 0} + dp_{i - 1, 1} \]

对于环的限制,改变初始值即可。

P5303 [GXOI/GZOI2019] 逼死强迫症

简要题意

有一个 \(2 \times n\) 的网格,每次你可以对于其中的 \(1 \times 2\) 或 \(2 \times 1\) 恰好两个不相邻的 \(1 \times 1\) 的位置染色。问全部染色的方案。

思路

设计 \(dp_i\) 表示填满前 \(i\) 列时的答案,\(f_i\) 表示只用 \(1 \times 2\) 或 \(2 \times 1\) 填满前 \(i\) 列的答案。

\(f_i\) 是好转移的,若最后是填两个 \(1 \times 2\) 则从 \(f_{i - 2}\) 转移而来;否则是最后填一个 \(1 \times 2\),从 \(f_{i - 1}\) 转移来。则 \(f_i = f_{i - 1} + f_{i - 2}\)。

考虑 \(dp_i\) 的转移,若最后是填两个 \(1 \times 2\) 则从 \(dp_{i - 2}\) 转移而来;若最后填一个 \(1 \times 2\),从 \(dp_{i - 1}\) 转移来;否则是最后 \(2 \times 2\) 的区域填 \(1 \times 1\),由于要求 \(1 \times 1\) 不相邻,因此贡献 \(2 \times f_{i - 2}\)。则 \(dp_{i} = dp_{i - 1} + dp_{i - 2} + 2 \times f_{i - 2}\)

这样又可以十分方便的进行矩阵加速。

Div. 2 E. Xor-sequences

简要题意

给定序列 \(a\),长度为 \(k\) 的序列 \(x\) 被称作“异或序列”,当且仅当以下两个条件全部满足:

  • \(\forall i \in [1,k] : x_i \in [1, n] \cap \Z\);
  • \(\forall i \in [1,k) : 3 \mid \mathrm{popcount}(a_{x_i}\mathbin{\mathrm{xor}} a_{x_{i + 1}})\)。

求有多少个异或序列。

思路

记 \(dp_{i, j}\) 表示第 \(i\) 位填 \(a_j\) 的方案数,有转移:

\[dp_{i, j} = \sum_{3 \mid a_j \oplus a_k} dp_{i - 1, k} \]

这样可以矩阵加速。

P3216 [HNOI2011] 数学作业

简要题意

求 \(1 \sim n\) 拼接后的结果。

思路

设 \(dp_i\) 表示 \(1 \sim i\) 拼接后的结果。有转移:

\[dp_i = dp_{i - 1} \times 10 ^ {1 + len(i)} + i \]

其中 \(len(i)\) 表示 \(i\) 在十进制下的位数。所以我们只要根据 \(len(i)\) 分段矩阵加速即可。

P16545 [EGOI 2026] 狐狸家族 / Fox Families

简要题意

多次操作,每次操作插入一段区间,每次将存在包含关系的区间合并为一个家族,每次操作后问剩下多少家族。

思路

插入区间类问题可以优先考虑 std :: set。那么对于一组操作 \((l, r)\),我们只需要分两种情况讨论:包含 \([l, r]\) 的区间和被 \([l, r]\) 包含的区间,这里可以泛化为合并两个家族。使用 std :: set 维护家族。

  • 不同家族可以排成一个顺序,前一个家族的所有左端点、所有右端点,都分别严格小于后一个家族的对应端点。

证明:考察一个家族外的区间,与它没有包含关系的区间只能分为两类:

  • 左右端点都比它小。
  • 左右端点都比它大。

这两者之间不可能存在包含关系。因此,一个与它无关的连通家族不可能同时出现在两类中。由此可知,不同家族不会相交。

于是我们对于每个家族维护其最小、最大左端点和最小、最大右端点。对于每个家族按其最小最短点排序,则相邻两个家族能保持独立,当且仅当靠左的家族最大左端点小于靠右的家族最小左端点,且靠左的家族最大右端点小于靠右的家族最小右端点。

P16541 [EGOI 2026] 饼干 / Biscuits

思路

首先博弈论 dp 考虑从最终态推初始态。设计 \(dp_{i}\) 表示填到后缀 \(i\) 时 B 的最大幸福度。有转移:

\[dp_i = \operatorname*{semax}_{j = i + 1} ^ {n + 1} dp_j + a_{j - 1} \]

其中 \(\operatorname*{semax}\) 表示次大值。

\(a_i\) 带修,因此直接懒惰转移是困难的。由于值域很小,所以可以直接维护最大值和次大值的差值的绝对值。维护 \(to_x\) 表示当前次大值为 \(x\) 所需的差值。对于后缀而言,这个可以从右往左合并,因此可以把这个问题放到线段树上做。

P11126 [ROIR 2024] 三等分的数组 (Day 2)

简要题意

把一个序列划分成若干三元组 \((x, x, x)\) 或 \((x + 1, x + 2, x + 3)\) 的方案。

思路

三元组的形式在值域上都是连续的,因此我们在值域上线性考虑这个问题。

设计 \(dp_{i, j, k}\) 表示在值域上考虑到 \(i\),\(i\) 还剩 \(j\) 个没分配,\(i - 1\) 还剩 \(k\) 个没分配的方案数。有转移:

\[dp_{i, j, k} \to dp_{i + 1, cnt_{i + 1} - 3 \times l - k, j - k} \]

其中 \(cnt_i\) 表示 \(i\) 出现的次数。

由于第二维 \(-3 \times l\) 这个转移是一个后缀和形式,因此我们可以先:

\[dp_{i, j, k} \to dp_{i + 1, cnt_{i + 1} - k, j - k} \]

再进行间隔为 \(3\) 的后缀和。

考虑分析状态数,\(j \le cnt_i, k \le cnt_{i - 1}\),因此总状态数为:

\[\sum_{i = 1} ^ m cnt_i \times cnt_{i - 1} \]

根据基本不等式,有:

\[n ^ 2 = (\sum_{i = 1} ^ m cnt_i) ^ 2 \ge \sum_{i = 1} ^ m cnt_i ^ 2 \ge \sum_{i = 1} ^ m cnt_{i} \times cnt_{i - 1} \]

因此时间复杂度可以做到 \(O(n ^ 2)\),空间复杂度可以进行滚动数组优化,也可以做到 \(O(m + n ^ 2)\)。

posted @ 2026-07-22 23:41  endswitch  阅读(33)  评论(0)    收藏  举报