2025.5-2025.6 常州集训 专题+模拟赛记录
2025.5-2025.6 常州集训 专题+模拟赛记录
记录下常州集训讲的专题以及模拟赛题
会抓紧补题的(流汗)
网络流
CF2046D For the Emperor!
P.S 以下称容量为 \(x\),费用为 \(y\) 的边为 \((x, y)\)
先缩点方便处理,scc 的 \(a\) 值即为其含有的点的 \(\sum a\)
考虑保持最大流总是 \(\sum a_i\),让一点收到计划时产生 \(-\text{inf}\) 的费用,发放计划时产生 \(1\) 的费用
跑最小费用最大流,最终根据最小费用除 \(\text{inf}\) 的商和余数算出"有多少个城市收到计划"以及"最少发放多少计划"
具体的,对第 \(i\) 个点:
-
对"最初第 \(i\) 个点有 \(a_i\) 名信使"的限制,考虑建限制点 \(P_i\),在源点 \(S\) 与 \(P_i\) 间连边 \((a_i, 0)\)
-
由于只产生一次收到计划的费用,考虑拆点,建入点 \(Q_i\) 与出点 \(R_i\),在 \(Q_i\) 与 \(R_i\) 间连边 \((1, -\text{inf})\) 与 \((+\infty, 0)\)
第一次走 \((1, -\text{inf})\) 表示该点收到计划,之后走 \((+\infty, 0)\) 不产生新的费用 (表示其他点的信使经过该点)
-
由于只产生一次发放计划的费用,考虑在 \(P_i\) 与 \(Q_i\) 间连边 \((1, 1)\),在 \(P_i\) 与 \(R_i\) 间连边 \((+\infty, 0)\)
走 \((1, 1)\) 表示在该点发放计划,接着会立刻走 \((1, -\text{inf})\) 表示该点收到计划;之后走 \((+\infty, 0)\) 不产生新的费用 (表示该点的信使经过自身)
-
点 \(i\) 的信使可以不参与之后的运送,在 \(R_i\) 与汇点 \(T\) 间连边 \((+\infty, 0)\)
对原图中边 \((u, v)\),在 \(R_u\) 与 \(Q_v\) 间连边 \((+\infty, 0)\) 即可
设最小费用为 \(c\),则有:
- 发放的计划数为 \(c_1 = (\text{inf}-(|c| \bmod \text{inf})) \bmod \text{inf}\)
- 收到计划的城市数为 \(c_2 = \displaystyle \frac{|c|+c_1}{\text{inf}}\)
那么 \(c_2 < n\) 即无解,反之 \(c_1\) 就是最小发放数量
这道题启示我们:
- 在处理"只有第一次经过产生费用"时,可以拆点连 \((1, -\text{inf})\) 与 \((+\infty, 0)\)
- 可通过赋极大费用,最后维护总费用中极大费用的相关信息处理一些东西
QOJ9224 Express Eviction
一个格子里有人,相当于 ban 掉了该格子四个端点上的边
有个很神的转化:从左上角到右下角联通,等价于对偶图上右上区域到左下区域不联通;具体的:
- 我们将格子看成点
- 对于每条被 ban 的边,将夹着其的两个格子连边
- 对于边界上被 ban 的格子,将其与相邻的左下区域 / 右上区域连边

感性理解大概是,若右上区域与左下区域联通,在从原图左上角走到右下角时,必然会跨过对偶图上连边的两格子中间夹的边,这样就经过了一条被 ban 的边;因此不存在合法路径
考虑连边刻画格子间的连通性,具体的:
-
枚举两被 ban 的格子,若两格子被 ban 的边连出来能够使它们联通,则将这两个格子连容量为 \(+\infty\) 的边
易得这等价于将两切比雪夫距离 \(\le 2\) 的被 ban 的格子连边
-
边界上被 ban 的格子仍然与相邻的左下区域 / 右上区域连容量为 \(+\infty\) 的边
由于我们能改变格子的被 ban 状态,一次会影响许多边,考虑拆点,在入点与出点间连容量为 \(1\) 的边
那么割掉入点与出点间的边即视为改变格子的被 ban 状态;直接跑最小割就是答案
这道题启示我们:可尝试使用对偶图刻画网格图连通性
ABC397G - Maximize Distance
注意到判断答案是否为 \(0\) 不弱于最小割,那么必然是网络流
首先答案显然有单调性,外层先套个二分,问题转化为求使最短路长度 \(>mid\) 最少需调整多少次
注意到最短路长度很小,不妨对每个点 \(i\) 按最短路长度值域开一列点 \(a_{i, 0}, a_{i, 1}, \cdots, a_{i, V}\) 代表到点 \(i\) 最短路长为 \(j\) 的状态
考虑用最小割刻画将边权 \(+1\) 的操作
具体的,对于原图上的边 \((u, v)\),对值域上的每个值 \(k\),进行如下连边:
- 从点 \(a_{u, k}\) 向点 \(a_{v, k+1}\) 连容量为 \(+\infty\) 的边,因为由三角形不等式,必然有 \(d_v \ge d_u+1\),这条边不能割
- 从点 \(a_{u, k}\) 向点 \(a_{v, k}\) 连容量为 \(1\) 的边,若割去代表将边 \((u, v)\) 的权 \(+1\)
对同一列点中相邻的两点 \(a_{i, j}\) 与 \(a_{i, j+1}\),我们连容量为 \(+\infty\) 的边
最后从源点 \(S\) 向 \(a_{1, 0}\)、从 \(a_{n, V}\) 向汇点 \(T\) 连容量为 \(+\infty\) 的边,直接跑最小割 check 是否 \(\le K\) 即可
这道题启示我们:若条件难以刻画,可以考虑直接暴力对值域中每个值开点
ARC142E - Pairing Wizards
首先,显然 \(A_i\) 越大越容易满足条件,将 \(A_i\) 向 \(a_i\) 下方调肯定不如直接调到 \(A_i = a_i\) 更优
两组限制不好搞,我们希望先去掉一组;对限制 \((x, y)\),不妨设 \(b_x < b_y\),注意到必然要求 \(A_x \ge b_x\) 且 \(A_y \ge b_x\),那么可以先对每个 \(A_i\) 求出一个下界 \(l_i\)
现在只剩下 \(A_x \ge b_y\) (别人满足自己) 或 \(A_y \ge b_y\) (自己满足自己) 的限制了
仍然不太好刻画;不过注意到值域很小,考虑直接对每个 \(i\) 按值域开点 \(A_{i, l_i}, A_{i, l_i+1}, \cdots, A_{i, V}\),代表 \(A_i\) 取 \(j\) 的状态
考虑用最小割刻画 \(A_i\) 的取值,若连到源点 \(S\) 则表示别人满足自己,若连到汇点 \(T\) 表示自己满足自己;具体的:
-
注意到 \(A_i \ge b_i\) 的满足方式只与 \(i\) 有关;若 \(l_i < b_i\),则建一个限制点 \(P_i\),从源点 \(S\) 向 \(P_i\) 连容量为 \(b_i-l_i\) 的边,若割掉表示 \(A_i\) 自己满足自己
-
对于 \(A_i\) 这一列相邻的两点 \(A_{i, j}\) 与 \(A_{i, j+1}\),从 \(A_{i, j+1}\) 向 \(A_{i, j}\) 连容量为 \(+\infty\) 的边
从 \(A_{i, l_i}\) 向汇点 \(T\) 连容量为 \(0\) 的边 (因为一开始就默认取 \(A_i = l_i\)),对于其他 \(A_{i, j}\),从 \(A_{i, j}\) 向汇点 \(T\) 连容量为 \(1\) 的边
因此,从 \(A_{i, l_i}\) 把连向汇点 \(T\) 的边一直割到 \(A_{i, k}\) 即视为取 \(A_i = k\)
-
对限制 \((x, y)\) (这里默认 \(b_x \le b_y\)),从 \(P_y\) 向 \(A_{x, b_y}\) 连容量为 \(+\infty\) 边即可
此处将链 \(A_y\) 到链 \(A_x\) 的边的贡献转移到了链 \(A_x\) 自身上,同时利用"割到 \(A_{i, j}\)"对"割到 \(A_{i, k}\ (k < j)\)"的包含关系避免对多个限制重复算贡献
那么直接跑最小割,累加上将 \(A_i\) 调到 \(l_i\) 的贡献就是答案
这道题启示我们:可尝试使用如下方式刻画"变量 \(x\) (值域为 \([l, r]\)) 的取值 \(\ge k\) ":
- 对 \(x\) 按照值域开一列点 \(x_l, x_{l+1}, \cdots, x_{r}\),从上向下连 \(+\infty\)
- 对每个 \(x_i\),向汇点 \(T\) 连容量为 \(1\) 的边
- 从源点 \(S\) 向限制点 \(P\) 连边,从 \(P\) 向 \(x_k\) 连容量为 \(+\infty\) 的边
CF1427G - One Billion Shades of Grey
考虑权只有 \(0\) 和 \(1\) 时怎么做
考虑用最小割刻画,最终连向源点 \(S\) 表示该点为 \(0\),连向汇点 \(T\) 表示该点为 \(1\);具体的:
-
对于未确定的点 \(u\),若其四连通范围内有为 \(0\) 的点,从源点 \(S\) 向 \(u\) 连一条容量为 \(1\) 的边;将这条边割去代表该点为 \(1\),产生 \(1\) 的贡献
-
对于未确定的点 \(u\),若其四连通范围内有为 \(1\) 的点,从 \(u\) 向汇点 \(T\) 连一条容量为 \(1\) 的边;将这条边割去代表该点为 \(0\),产生 \(1\) 的贡献
-
对于未确定的相邻两点 \(u, v\),\(u\) 与 \(v\) 间连一条容量为 \(1\) 的边;将这条边割去代表两点不同,产生 \(1\) 的贡献
注意到填的数只能是边界上有的数,设为 \(w_1, w_2, \cdots, w_k\ (w_1 < w_2 < \cdots < w_k)\),考虑转化 \(\boldsymbol{|w_r-w_l| = \sum_{i=l+1}^{r} (w_i-w_{i-1})}\)
那么枚举 \(w_i\),按照与 \(w_i\) 的大小关系将权变为 \(0,1\) 跑最小割即可;不过这样时间复杂度无法接受
注意到当枚举的 \(w_i\) 变大时,格子上填的数 ( \(0/1\) ) 单调不增 (感性理解上,边界上的 \(0\) 变多,进而连边时将一些连向 \(T\) 的边改为连向 \(S\),此时割连向 \(T\) 的边更优)
于是考虑整体二分;设 \(br(l, r, S)\) 表示值域为 \([w_l, w_r]\),集合 \(S\) 中的点未确定,每次:
- 以 \(w_{mid}\) 为基准跑最小割
- 搜出连向源点 \(S\) 的集合 \(S_l\) 与连向汇点 \(T\) 的集合 \(S_r\),递归 \(br(l, mid, S_l)\) 与 \((mid+1, r, S_r)\) 即可
边界为 \(l = r\) 时将 \(S\) 中的点赋为 \(w_l\);最终可以确定所有点的取值,据此计算答案即可
这道题启示我们:
- 当只有两种决策时,可考虑最小割,通过连向源点 \(S\) 与连向汇点 \(T\) 代表两种决策,用边权刻画选择代价
- 可考虑将值域转化为 \(0/1\) 以简化问题
AGC031E - Snuke the Phantom Thief
发现直接建模没有前途,考虑转化
以第一种约束为例,注意到"横坐标 \(\le a_i\) 的珠宝最多偷 \(b_i\) 颗"等价于"将选择的珠宝按横坐标从小到大排序,下标为 \(b_i+1\) 的珠宝的横坐标 \(> a_i\)"
因此,我们在 \(x, y\) 两个方向上引入"在选好的珠宝中的下标"一维,考虑将对珠宝坐标的限制转化为放到某个下标上的限制;具体的:
- 设 \(L_i, R_i\) 表示在 \(x\) 方向从小到大排序,下标为 \(i\) 的珠宝的 \(x\) 坐标需要在 \([L_i, R_i]\) 间
- 设 \(U_i, D_i\) 表示在 \(y\) 方向从小到大排序,下标为 \(i\) 的珠宝的 \(y\) 坐标需要在 \([U_i, D_i]\) 间
与转化的例子类似,容易将给出的 \(m\) 个限制转化为对某个 \(L_i\) 或 \(R_i\) 或 \(U_i\) 或 \(D_i\) 的赋值 (准确来说应为取 \(\max\) 或取 \(\min\),因为要取最严的)
由于是排好序后的下标,以 \(L_i\) 为例,转化后还要进行 \(L_i = \max(L_i, L_{i-1})\) 的递推;其他方向同理
那么现在我们可以简单判断第 \(i\) 个珠宝能否放在某个下标上
枚举下标总数 \(k\),问题转化为:\(x\) 方向有 \(k\) 个坐标,\(y\) 方向有 \(k\) 个坐标,给点分配恰一个 \(x\) 方向的坐标与恰一个 \(y\) 方向的坐标,最大化分配了坐标的点的权值和
考虑拆点费用流:
- 对 \(x\) 坐标建 \(k\) 个点,从源点 \(S\) 向这 \(k\) 个点连 \((1, 0)\) 边
- 对 \(y\) 坐标建 \(k\) 个点,从这 \(k\) 个点向汇点 \(T\) 连 \((1, 0)\) 边
- 对 \(n\) 个珠宝,第 \(i\) 个珠宝建入点 \(P_i\) 与出点 \(Q_i\):
- \(P_i\) 与 \(Q_i\) 间连 \((1, v_i)\) 边
- 符合条件的 \(x\) 方向下标向 \(P_i\) 连 \((1, 0)\) 边
- \(Q_i\) 向符合条件的 \(y\) 方向下标连 \((1, 0)\) 边
直接求最大费用最大流即可
这道题启示我们:可尝试使用如下方式刻画"不重地将 \(k\) 个属性分给 \(n\) 个物品 (可有物品不分到属性,可有分配条件),每个分到属性的物品 \(i\) 有贡献 \(F(i)\)":
- 对 \(k\) 个属性建 \(k\) 个点,从源点 \(S\) 向这 \(k\) 个点连 \((1, 0)\) 边
- 对 \(n\) 个物品,第 \(i\) 个物品拆成入点 \(P_i\) 与出点 \(Q_i\):
- \(P_i\) 与 \(Q_i\) 间连 \((1, F(i))\) 边
- 符合条件的属性向 \(P_i\) 连 \((1, 0)\) 边
- \(Q_i\) 向汇点 \(T\) 连 \((1, 0)\) 边
最小费用最大流 / 最大费用最大流即可
容易发现,这种处理方式可以推广到以下几种情况:
- 物品 \(i\) 可以分配 \(C(i)\) 个属性
- 第 \(i\) 个属性可以分配 \(H(i)\) 次
待补:
背包
P4389 付公主的背包
设第 \(i\) 种商品的生成函数 \(\displaystyle F_i(x) = 1+x^{v_i}+x^{2v_i}+\cdots = \frac{1}{1-x^{v_i}}\)
显然最终要求的就是 \(\displaystyle F(x) = (\prod_{i=1}^{n} F_i(x)) \bmod x^{m+1}\),体积为 \(w\) 时的答案即为 \(F(x)\) 中 \(x^w\) 项的系数
对于连乘的形式,一种常见的处理方式是取 \(\ln\) 转换为加法后再 \(\exp\) 回来,我们有:
\(\displaystyle \prod_{i=1}^{n} F_i(x) = \exp(\ln (\prod_{i=1}^{n} F_i(x))) = \exp(\sum_{i=1}^{n} \ln(F_i(x)))\)
那么现在的问题就是如何快速求 \(\ln(F_i(x))\);不妨导完积回来试试
\(\displaystyle \int (\ln'(F_k(x))\ \text{dx}\)
\(\displaystyle = \int (\frac{F_k'(x)}{F_k(x)})\ \text{dx}\)
\(\displaystyle = \int ((1-x^{v_k}) \sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1}))\ \text{dx}\)
\(\displaystyle = \int (\sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1}) - x^{v_k} \sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1}))\ \text{dx}\)
\(\displaystyle = \int (\sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1}) - \sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1} \times x^{v_k}))\ \text{dx}\)
后面乘上去的 \(x^{v_k}\) 很烦,此时有个厉害的想法是将后半部分的求和整体左移一位,即令 \(i \leftarrow i-1\),刚好消去 \(x^{v_k}\)
注意到 \(i = 0\) 时,\(iv_k \times x^{iv_k-1} \times x^{v_k} = 0\),左移后显然也是 \(0\),因此正确性没问题
\(\displaystyle = \int (\sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1}) - \sum_{i=1}^{\infty} ((i-1)v_k \times x^{(i-1)v_k - 1} \times x^{v_k}))\ \text{dx}\)
\(\displaystyle = \int (\sum_{i=1}^{\infty} (iv_k \times x^{iv_k - 1}) - \sum_{i=1}^{\infty} ((i-1)v_k \times x^{iv_k - 1}))\ \text{dx}\)
\(\displaystyle = \int (\sum_{i=1}^{\infty} (v_k \times x^{iv_k - 1}))\ \text{dx}\)
\(\displaystyle = \sum_{i=1}^{\infty} (\frac{1}{i} x^{iv_k})\)
带回原式,即得
\(\displaystyle \exp(\sum_{i=1}^{n} \ln(F_i(x)))\)
\(\displaystyle = \exp(\sum_{k=1}^{n} \sum_{i=1}^{\infty} (\frac{1}{i} x^{iv_k}))\)
注意到最终所求是在 \(\bmod x^{m+1}\) 意义下的,于是我们只需保留 \(iv_k \le m\) 的项即可;记 \(c_i\) 表示满足 \(v_k = i\) 的 \(v_k\) 的个数,则:
\(\displaystyle = \exp(\sum_{i=1}^{m} \sum_{j=1}^{\lfloor \frac{m}{i} \rfloor}(\frac{c_i}{j} x^{ij}))\)
于是我们可以 \(O(m \ln m)\) 求出 \(\exp\) 里面的柿子,再 \(O(m \log m)\) 多项式 \(\exp\) 回去即可
这道题启示我们:无限背包,\(n, m, v_i \le 10^5\),求 \([1, m]\) 方案数,可以考虑生成函数 + \(\ln\) + \(\exp\)
CF1290F - Making Shapes
由于最后要生成凸包,若向量集合确定,凸包形状也是唯一确定的
不妨设第 \(i\) 个向量选了 \(c_i\) 次,考虑如何刻画这些向量可以形成合法的凸包:
-
由于最终必然会走回来,显然有 \(\displaystyle \sum_{i=1}^{n}c_ix_i = 0\) (即 \(\displaystyle \sum_{x_i>0} c_ix_i = \sum_{x_i<0} c_i(-x_i)\) ) 且 \(\displaystyle \sum_{i=1}^{n}c_iy_i = 0\) (即 \(\displaystyle \sum_{y_i>0} c_iy_i = \sum_{y_i<0} c_i(-y_i)\) )
-
对于"包含在 \(m \times m\) 的正方形中"的限制,由于构造过程必然是先往前走,走到一点后回头,直到回到起点
那么只需满足 \(\displaystyle \sum_{x_i > 0} c_ix_i \le m\) 且 \(\displaystyle \sum_{y_i > 0} c_iy_i \le m\)
注意到 \(n, x_i, y_i\) 的值域都非常小,考虑对 \(\{c_i\}\) 数位 DP,逐位确定每个 \(c_i\) 当前位的值
具体的,在数位 DP 的过程中,我们维护如下状态:
-
\(\text{step}\),表示当前从低到高填到第几位;不从高到低 DP 是因为我们需要维护进位信息,向高位的进位不会对已经填好的低位产生影响
-
\(\text{px}\),表示当前对 \(\displaystyle \sum_{x_i>0} c_ix_i\) 的进位 (注意不是总进位,是只对后一位及之后);同时维护 \(\text{nx}\),表示当前对 \(\displaystyle \sum_{x_i<0} c_i(-x_i)\) 的进位;同理维护 \(\text{py}\) 与 \(\text{ny}\),含义类似
只要每次判断 \(\text{px}\) 与 \(\text{py}\)、\(\text{nx}\) 与 \(\text{ny}\) 当前位相等,即可判断最终是否有 \(\displaystyle \sum_{x_i>0} c_ix_i = \sum_{x_i<0} c_i(-x_i)\) 与 \(\displaystyle \sum_{y_i>0} c_iy_i = \sum_{y_i<0} c_i(-y_i)\)
-
\(\text{fx}\ (0/1)\),表示当前 \(\displaystyle \sum_{x_i>0} c_ix_i\) 与 \(m\) 的后 \(\text{step}\) 位的大小关系 ( \(0\) 表示 \(\le\) );同理维护 \(\text{fy}\ (0/1)\),含义类似
转移时暴力 \(O(2^n)\) 枚举每个 \(c_i\) 当前填什么即可;边界条件为 \(\text{px, nx, py, ny, fx, fy}\) 全 \(0\) 时合法
时间复杂度大概为 \(O(2^n \times 4 \times 20^4 \times \log m)\)
这道题启示我们:无限背包,\(n, v_i\) 极小,\(m\) 极大,可以考虑数位 DP,维护进位
CF1856E2 - PermuTree (hard version)
对于一点 \(u\),我们希望将其子树内的点黑白染色,使得不同色且不在一个儿子子树内的点尽量多
注意到对于 \(u\) 的儿子 \(v\) 的子树中的一点,将其颜色翻转带来的贡献变化与 \(v\) 子树的信息无关;因此我们必定将整个子树内的点的颜色调成相同
那么问题转化为将 \(u\) 的儿子划分为两个集合 \(S, T\),最大化 \(\displaystyle (\sum_{a \in S} siz_a) \times (\sum_{b \in T} siz_b)\)
直接做可行性背包是 \(O(n^2)\) 的,考虑优化:
- 若重儿子子树大小大于其余所有子树大小之和,显然直接选重儿子
- 注意到转移柿子形如 \(f_i \leftarrow f_{i-siz_v}\),即为左移 \(siz_v\) 后按位或,可以上
bitset - 由 \(\sum siz_v \le n\),不同的 \(siz_v\) 只有 \(O(\sqrt n)\) 级别;于是可以统计每个 \(siz_v\) 的出现次数后进行二进制分组优化多重背包
实现上,可以考虑暴力把所有可能用到的大小为 \(2^k\) 的 bitset 全都开出来,转移时找第一个大于子树大小的;注意别爆栈
时间复杂度 \(\displaystyle O(\frac{n \sqrt n}{w})\),证明参见这里
这道题启示我们:\(01\) 可行性背包,\(\sum v_i \le n\),\(m\) 与 \(n\) 同量级,可以考虑找出本质不同的 \(v_i\) 后二进制分组 +
bitset优化多重背包
P9140 [THUPC 2023 初赛] 背包
考虑同余最短路
在可行性背包中,我们选取 \(v_i\) 最小的物品作为基准物品,这样若重复经过一点,可将路径中两点间的部分替换为若干基准物品
现在引入了价值一维;在"替换为若干基准物品"这一过程中,我们必定希望基准物品性价比最高,因此选择 \(\displaystyle \frac{c_i}{v_i}\) 最大的物品作为基准物品
设基准物品的体积为 \(v_0\),价值为 \(c_0\);对于背包方案 \((V', C')\),其价值为 \(\displaystyle \frac{V-V'}{v_0}c_0+C'\),因此对于所有\(\bmod m\) 同余的 \(V'\),我们希望 \(\displaystyle C'-\lfloor \frac{V'}{v_0} \rfloor c_0\) 尽量大
综上,对于物品 \((v_i, c_i)\),从点 \(k\) 连向 \((k+v_i) \bmod v_0\) 时,边权应为 \(\displaystyle c_i-\lfloor \frac{v_i}{v_0} \rfloor c_0\)
设 \(m\) 为 \(v_i\) 的值域上界,由于不会经过重复点,\(V'\) 最大取到 \(m^2\) ,而数据范围保证 \(V \ge m^2\),正确性没问题;时间复杂度 \(O(nm)\)
这道题启示我们:无限背包,设 \(m\) 为 \(v_i\) 的上界,求恰好装到 \(V\) 的最大价值 / \([L, R]\) 中有解个数,且 \(V \ge m^2\) / \(L \ge m^2\),可以考虑 \(O(nm)\) 同余最短路
Gym101064L - The Knapsack problem
设 \(m\) 为 \(w_i\) 的值域上界,\(S \ge m^2\) 就同余最短路,反之直接暴力
Gym101002H - Jewel Thief
注意到珠宝体积值域很小,考虑对体积相同的分组处理
设当前组体积为 \(v_i\),显然转移时只会拼上 \(v_i\) 的整数倍,于是进一步考虑按照\(\bmod v_i\) 的余数处理
将体积为 \(v_i\) 的珠宝从大到小排序,容易发现每次转移拼上的是一段前缀;其实还有更厉害的事情:转移满足决策单调性
下面给出对决策单调性的证明:
不妨设 \(s_k\) 为前缀和数组,\(rem\) 为当前余数,设状态 \(f_k\) 表示总体积为 \(rem+k \times v_i\) 时的最大价值;那么成本函数 \(w(a, b)\) 即为 \(f_a+s_{b-a}\)
对于决策点 \(x, y\ (x < y)\),若对于 \(f_i\) 有 \(w(x, i) = f_x+s_{i-x} < w(y, i) = f_y+s_{i-y}\),则对于 \(j>i\):
-
\(w(x, j) = f_x+s_{j-x} = w(x, i)+(s_{j-x}-s_{i-x})\)
-
\(w(y, j) = f_y+s_{j-y} = w(y, i)+(s_{j-y}-s_{i-y})\)
-
显然 \(s_{j-x}-s_{i-x}\) 与 \(s_{j-y}-s_{i-y}\) 都是一段区间和,且两个区间长度均为 \(j-i\),前者的起点更靠后;由于珠宝从大到小排序,此时选 \(x\) 为决策点必然不优
综上,转移满足决策单调性;直接分治优化即可
设 \(m\) 为 \(s\) 的值域上界,时间复杂度 \(O(mk \log k)\)
这道题启示我们:\(01\) 背包,求能装到 \(\le k\) 的最大价值,体积值域较小时可以考虑按体积分组 + 决策单调性优化 DP
P8392 [BalticOI 2022] Uplifting Excursion (Day1)
由于 \(l\) 与 \(a_i\) 太大,无法直接背包;考虑先贪心地选一些东西,限制背包的容量范围
具体的,我们先把所有物品都选上,记此时重量和为 \(s\):
- 若 \(s > l\),则从重量为 \(m\) 的物品开始往回删,一直删到 \(s \le l\)
- 若 \(s < l\),则从重量为 \(-m\) 的物品开始往后删,一直删到 \(s \ge l\)
容易发现操作后必然满足 \(s \in [l-m, l+m]\);此时我们需要调整一些物品的选择个数使得 \(s = m\),注意到:
- 调整过程中始终有 \(s \in [l-m, l+m]\),否则可以将使 \(s\) 超出范围的那次操作与之后使 \(s\) 跳回范围内的一段操作交换
- 显然 \(s\) 不会经过同一个值 \(v\) 两次,否则第一次到达 \(v\) 后的操作可以全扔掉
重量为 \(0\) 的物品我们必定全选;剩下的物品对总重量的影响至少为 \(1\),至多有 \(2m\) 次有效影响,重量变化至多为 \(2m^2\)
那么只保留 \(2m^2\) 的值域跑多重背包即可;上个二进制分组优化,时间复杂度 \(O(m^3 \log m)\)
这道题启示我们:可以在 DP 前贪心选择一部分以限制 DP 值域
待补:
- QOJ9870 - Items
- QOJ9517 - 分道扬镳
- Gym103428C - Assign or Multiply
- P6261 [ICPC 2019 WF] Traffic Blights
- P7606 [THUPC 2021] 混乱邪恶
- QOJ9491 - 生命的循环
连通性问题
QOJ10272 - Majority Graph
注意到在连上一些边后,其他一些边可以被已经连上的边隐式覆盖 (如连 \((a, b)\) 与 \((b, c)\) 就隐式覆盖了边 \((a, c)\) ) ;考虑如何确定连边方案以隐式覆盖所有边
枚举众数 \(x\),我们套路的记数组 \(b_i\),当 \(a_i = x\) 时 \(b_i = 1\),反之 \(b_i = -1\);再记 \(s_i\) 表示 \(b_i\) 的前缀和,这样区间 \([l, r]\) 有众数就转化为 \(s_r-s_{l-1} > 0\)
考虑分讨每类边 \((i, j)\) 的连边方案:
-
\(a_i \ne x, a_j \ne x\):记 \(p\) 为 \([i, j]\) 间最靠前的值为 \(x\) 的位置,\(q\) 为 \([i, j]\) 间最靠后的值为 \(x\) 的位置,我们必然会连 \((i, q), (p, j), (p, q)\),这样就隐式覆盖了 \((i, j)\)
综上,无需考虑这样的边 \((i, j)\)
-
\(a_i = x, a_j = x\):若 \(s_j-s_i = 0\),必可找到 \((i, j]\) 间第一个 \(a_k = x\) 且 \(s_k-s_i = 0\) 的位置 \(k\) 并连边 \((i, k)\),对 \([k, j]\) 等同理操作,这样就隐式覆盖了 \((i, j)\)
若 \(s_j-s_i > 0\),类似的,我们可找到 \((i, j]\) 间第一个 \(a_k = x\) 且 \(s_k-s_i = 1\) 的位置 \(k\) 并连边 \((i, k)\),对 \([k, j]\) 等同理操作,差为 \(0\) 时再按上一种情况做即可
综上,对于每个位置 \(i\),我们只需:
-
找到其后第一个满足 \(a_p = x\) 且 \(s_p-s_i = 0\) 的 \(p\)
-
找到其后第一个满足 \(a_q = x\) 且 \(s_q-s_i = 1\) 的 \(q\)
-
连边 \((i, p), (i, q)\) 即可
实现时可以直接二分;对于这类情况,边数是 \(O(n)\) 的
-
-
\(a_i = x, a_j \ne x\):注意到这种情况是有包含关系的,即对于以 \(j\) 结尾的一段极长非 \(x\) 连续段 (不妨设为 \([k, j]\) ),\(i\) 向其中的每个点都连边
显然所有 \(a_p = x\) 的位置将原序列割成了很多段;注意到,若我们知道 \(k, j\) 处于哪一段中,\(i\) 必然取这一段前所有 \(a_p = x\) 的位置中 \(s_p\) 最小的
证明:显然 \(i\) 的前缀和最小时更容易向后连边;此外对于 \(j\) 前面所有 \(a_p = x\) 的位置 \(p\),若能连边 \((p, j)\),可直接把 \((p, j)\) 换成 \((p, i),(i, j)\),肯定不漏;证毕
综上,我们可以枚举 \(j\) 处于哪一段中,此时 \(i\) 的位置唯一确定,再由 \(i\) 的位置就可以直接二分出 \(k, j\) 的位置
考虑将连边 \((i, k), (i, k+1), \cdots, (i, j)\) 转化为连边 \((i, k), (k, k+1), (k+1, k+2), \cdots, (j-1, j)\)
边 \((i, k)\) 直接暴力连,剩下的开个差分数组维护即可;操作数也是 \(O(n)\) 的
- \(a_i \ne x, a_j = x\):本质上与上一种情况相同,再倒着做一遍即可
综上,建边复杂度为 \(O(n \log n)\) (要二分),实际边数为 \(O(n)\),建出图后直接搜即可;总时间复杂度 \(O(n \log n)\)
这道题启示我们:在给定固定连边策略、对每两点都尝试连边时,可以考虑如何去掉冗余的边
CF1062F - Upgrading Cities
考虑拓扑排序;注意到"别人能到达自己"与"自己能到达别人"本质相同,建反图再做一遍即可;下面只考虑"自己能到达别人"
由于给定的图是 DAG,注意到由拓扑排序的性质,对于点 \(i\),当 \(i\) 刚出队时:
- 点 \(i\) 不可达已出队的点
- 未入队的点不可达 \(i\)
- 同在队中的点与 \(i\) 互相不可达
设点 \(i\) 刚出队时队列大小为 \(|q|\):
-
\(|q| = 0\),那么还未入队的点都由 \(i\) 扩展而来,换句话说,点 \(i\) 可达未入队的所有点
-
\(|q| = 1\),设队列中的点为 \(j\),此时 \(i\) 不可达 \(j\);那么只要 \(i\) 不可达后面任一个还未入队的点,\(i\) 就不符合要求
因此,我们只考虑能被 \(i\) 和 \(j\) 直接扩展得到的点;考察哪些点只能由 \(j\) 扩展得到,对于一未入队的点 \(k\):
- 首先,需要存在边 \((j, k)\),这样其才能由 \(j\) 扩展到
- 其次,该点入度只能为 \(1\),这样其才只能由 \(j\) 扩展到
综上,当点 \(k\) 入度为 \(1\) 且这条边恰为 \((j, k)\) 时,\(i\) 不可达 \(k\),此时 \(i\) 不符合要求
-
\(|q| \ge 2\),显然 \(i\) 不符合要求
那么直接模拟,记录每个点"可达其他点 / 被其他点可达"的个数,最终判断是否 \(\ge n-2\) (还要除去自己) 即可
时间复杂度 \(O(n+m)\)
这道题启示我们:可考虑使用拓扑排序刻画 DAG 上可达点个数
P9829 [ICPC 2020 Shanghai R] Traveling Merchant
将 H 看成染黑色,将 L 看成染白色,令异色边为两端点颜色不同的边,同色边为两端点颜色相同的边
那么我们需要判断是否存在一条简单路径 \(1 \rightarrow u \rightarrow v\),满足:
- \(1 \rightarrow u \rightarrow v\) 的路径上每条边都是异色边
- 存在同色边 \((u, v)\) (因此走到 \(v\) 后我们可以绕回 \(u\),之后在 \(u\) 与 \(v\) 间无限绕圈)
- \(1 \rightarrow u\) 的部分与 \(u \rightarrow v\) 不交 (即不经过环上的点)
只有一条同色边的限制是苛刻的,考虑先把只含异色边的图建出来,再枚举每条同色边判断
设同色边为 \((u, v)\),我们只需要判断在新图上是否存在从 \(1 \rightarrow u\) 且与环不交的简单路径
注意到点双可以很好的刻画两点间的连通关系 (包含了两点间所有简单路径);这启示我们建出新图的圆方树
不妨设 \(u\) 在圆方树上的父亲方点为 \(u'\),\(v\) 在圆方树上的父亲方点为 \(v'\);再设 \(\text{lca}(u', v') = w'\)
由圆方树的性质:
-
\(u \rightarrow v\) 环上的点集必然包含于树上 \(u' \rightarrow w' \rightarrow v'\) 经过的方点中的点集的并
-
对树上 \(u' \rightarrow w' \rightarrow v'\) 经过的每个方点,都要选至少一个点出来组成 \(u \rightarrow v\) 环上的点集
因此,存在满足上述条件的简单路径等价于 \(w' = u'\) 或 \(w' = v'\);反之,从 \(1\) 走到 \(u\) 时必然经过 \(w' \rightarrow u'\) 的部分,与环有交,矛盾
特殊的,当 \(u = 1\) 或 \(v = 1\) 时 (也就是 \(u'\) 或 \(v'\) 不存在),显然成立
综上,我们按异色边建图,对 \(1\) 的连通块建圆方树,枚举同色边判断 \(\text{lca}\) 即可
时间复杂度 \(O(m \log n)\)
这道题启示我们:可考虑使用圆方树判断形如"是否存在 \(a \rightarrow u\) 的简单路径满足不经过 \(u \rightarrow v\) 的简单路径"的问题
AGC071C - Orientable as Desired
题目给出的限制很严,考虑先赋值一些特殊的 \(X\)
一种较为特殊的情况是 \(\mathbf{X = (0, 0, \cdots, 0)}\),此时每个点要么全连进来,要么全连出去;此时显然不存在奇环,\(G\) 必须为二分图
考虑由特殊情况逐渐调整,先将 \(X\) 调整为 \(\mathbf{(v, 0, 0, \cdots, 0)}\);此时若将 \(1\) 号点挖去,其余点仍须满足二分图的条件
更进一步,对于每个连通块,实际仅有原定向方案 / 将原定向方案的所有边翻转两种操作方式
由于不存在奇环,每个点连向 \(1\) 的边的方向必定相同;既然可以整体翻转,一个连通块就可以选择 全贡献给 \(1\) / 全不贡献给 \(1\)
设 \(1\) 在每个连通块中的度数为 \(a_1, a_2, \cdots, a_k\),问题即变为是否可以选择若干 \(a_i\) 凑出 \(v\)
这是一个经典问题,将 \(a_i\) 从小到大排序,初始令 \(S = 0\),表示当前可以凑出 \([0, S]\);依次遍历 \(a_i\):
- 若 \(a_i > S+1\),显然无法凑出 \(S+1\),不成立
- 反之,\([0, S+a_i]\) 均可以凑出,令 \(S \leftarrow S+a_i\) 即可
感性理解上,按步子小到步子大走可以尽可能避免 \(S\) 跳过一些数;我们能表示的数又总是一段从 \(0\) 开始的前缀,因为我们只需要判断第一次跳数即可
我们继续对一些特殊的图进行分析,比如树
考虑延续这种操纵连通块以满足自身度数要求的思想:
- 对于非叶子节点 \(u\),对其每个叶子 \(v\) 的边 \((u, v)\) 定向,以满足自身的度数要求 (只需凑向根定向 / 向叶子定向两个方向中能凑出的一个即可)
- 对于叶子 \(u\),显然无论如何定向都满足要求
因此对于树,必定不存在满足要求的 \(X\)
接下来尝试推广到图上;我们自然希望往树的形式凑,于是考虑建出圆方树,在圆方树上考虑
考虑与树类似的策略,只不过之前可以直接操纵儿子,现在操纵的是儿子点双;具体的:
-
对于方点 \(u\) 与其父亲圆点 \(fa\),对于 \(u\) 点双未被定向的边,按照 \(X = (0, 0, \cdots, 0)\) 的方式定向
-
对于圆点 \(u\) 与其父亲方点 \(fa\),\(fa\) 点双中的所有边在之前已被定向;考虑让 \(u\) 操纵其连向父亲点双与儿子点双中的边,凑出自己的度数限制
由上述 \(X = (v, 0, 0, \cdots, 0)\) 的调整过程,容易得到这么做的正确性
那么我们只需对每个(圆)点 \(i\) 找出其在每个相邻连通块中的度数 \(a_1, a_2, \cdots, a_k\),判断是否能凑出自己的度数限制即可
时间复杂度 \(O(m \log m)\)
这道题启示我们:当题目限制非常严格时,可以考虑先带一些特殊值入手,由最特殊的情况逐渐调整并发掘性质,再围绕性质尝试解决一般问题
具体的,对于一般图上的问题,可以考虑搬到树上发掘性质,再尝试建圆方树转化为树上问题
CF475E - Strongly Connected City 2
首先有经典结论:边双可以定向成强连通分量
对于证明,大概考虑每次找个小环,定向成"圈"的形式后将这个小环缩成一个点,重复做即可
那么缩下边双,问题从图转化到了树上
手玩一下可以发现,对于根 \(rt\),最优方案下必然将部分 \(rt\) 的子树全部向 \(rt\) 定向,其余子树全部向叶子定向
考虑反证,对于一种其他方案,去证归纳调整到上述定向方式必定不劣:
-
从深度大到深度小考虑;设当前处理节点 \(u\),归纳得节点 \(u\) 子树中全部向 \(rt\) 定向 (向叶子定向同理),考察边 \((u, fa_u)\) 的定向情况
设 \(siz_u\) 为 \(u\) 的子树大小,\(x\) 为 \(fa_u\) 向 \(fa_u\) 子树外走能到达的节点数量,\(y\) 为 \(fa_u\) 子树外向 \(fa_u\) 走能到达 \(fa_u\) 的节点数量
-
若 \((u, fa_u)\) 向 \(rt\) 定向,额外贡献为 \(siz_u \times x\)
-
若 \((u, fa_u)\) 向叶子定向,同时将 \(u\) 子树全部翻转,额外贡献为 \(siz_u \times y\)
对于 " \((u, fa_u)\) 向叶子定向时,仅翻转 \(u\) 子树部分边是不优的"的证明:
- 归纳可得 \(u\) 子树内边全部向 \(rt\) / 全部向叶子定向时,子树内贡献最大;因此仅翻转部分边,子树内贡献不优
- 对于 \(u\) 子树的每个点,显然都会选择贡献 \(x, y\) 中较大的那个;那么仅翻转部分边会使得一部分较大的贡献变为较小的贡献,子树外贡献也不优
综上,子树内外都不优,证毕
-
注意到,额外贡献只与 \(x, y\) 的大小关系有关,而 \(fa_u\) 子树内对 \(x, y\) 没有影响
那么 \(fa_u\) 的每个儿子决策都是一样的,我们根据 \(x, y\) 的大小关系选择是否全部翻转即可,证毕
-
综上,枚举根直接背包即可,时间复杂度 \(O(n^2)\)
这道题启示我们:定向可达性可以考虑由"边双可以定向成强连通分量"的结论,缩边双后转化为树上问题,再进行分析
CF1338E - JYPnation
首先有经典结论:竞赛图缩点后是由一条极长链和许多前向边组成的图
可以归纳证明,一个 SCC 必然包含三元环 (由于是竞赛图,一个大环会被不断割成两半);由题目要求,易得:**除了链尾 SCC,其余 SCC 的大小均为 \(1\) **
Key Observation:答案不超过 \(3\)
反证,若存在长度 \(\ge 4\) 的最短路,考虑把这五个点拎出来;由于是竞赛图,两点间必有边,又不能产生更短的路径,于是其余边的方向均确定

(来自 Social_Zhao 老师的精美图片)
由图可得,三元环 \((c, d, e)\) 均向点 \(a\) 连边,矛盾
由于总数确定,长度分别为 \(1, 2, 3, 614 \times n\) 的点对的数量我们只需确定三类即可:
-
对于长度为 \(614 \times n\) 的点对,易证只产生在链上后面的点 \(\rightarrow\) 链上前面的点间;实现时一次拓扑排序即可求出
-
对于长度为 \(1\) 的点对,显然为 \(C_{n}^{2}\)
-
求长度为 \(2\) 的点对必定比长度为 \(3\) 的点对简单;考虑长度为 \(2\) 的点对
设其为 \((u, v)\),则必然有:
- 存在中转点 \(w\),即使得存在边 \(u \rightarrow w\) 与 \(w \rightarrow v\)
- \(u\) 与 \(v\) 两点间边的方向为 \(v \rightarrow u\) (不然长度就是 \(1\) 了)
注意到一个很好的性质,此时 \((u, v, w)\) 恰形成一个三元环
此时我们有暴力枚举 \(u, v, w\),时间复杂度 \(O(n^3)\) 的判断方法;考虑对枚举 \(w\) 的过程进行优化
对于 \(u\) 的另一出边对应的点 \(k\),由题目性质,若 \(w \rightarrow k\),则必有 \(k \rightarrow v\);反之,三元环 \((u, v, w)\) 均向 \(k\) 连边,矛盾
换句话说,若 \(w \rightarrow k\),则 \(k\) 必然也是中转点;那么 \(u, v\) 的中转点形成了类似拓扑关系
具体的,考虑找到 \(u\) 出边对应的点中"拓扑序最大的点" (\(u\) 出边对应的其他点都向它连边);由上,只需判断这个点是否是中转点即可
这部分时间复杂度优化到 \(O(n^2)\)
总时间复杂度 \(O(n^2)\)
这道题启示我们:竞赛图可达性,可以考虑缩 SCC 后在极长链+前向边的图上考虑
待补:
计数
全都得补……
数据结构
全都得补 × 2……
模拟赛题
05.22 - 1.奇环
先考虑特殊性质 A;此时相当于给定 \(k\) 个连通块,我们要加 \(k-1\) 条边把它连成树
设第 \(i\) 个连通块的大小为 \(s_i\);若有 \(\forall i,\ s_i = 1\),就是经典的 Prüfer 序列问题,结论为 \(k^{k-2}\)
这启示我们将每个连通块看成一个点,凑出 Prüfer 序列问题的形式
具体的,由于连通块有大小,先枚举每个连通块的度数 \(d_i\),则 \(\sum d_i = 2(k-1) = 2k-2\);对于给定的 \(d_i\),方案数为:
\(\displaystyle \begin{pmatrix} k-2 \\ d_1-1, d_2-1, \cdots, d_k-1 \end{pmatrix} \prod_{i=1}^{k} s_i^{d_i}\)
那么总方案数即为:
\(\displaystyle \sum_{d_1+d_2+\cdots+d_k = 2k-2,\ d_i \ge 1} \begin{pmatrix} k-2 \\ d_1-1, d_2-1, \cdots, d_k-1 \end{pmatrix} \prod_{i=1}^{k} s_i^{d_i}\)
注意到形式非常像多元二项式定理:\(\displaystyle (a_1+a_2+\cdots+a_k)^n = \sum_{b_1+b_2+\cdots+b_k=n,\ b_i \ge 0} \begin{pmatrix} n \\ b_1, b_2, \cdots, b_k \end{pmatrix} \prod_{i=1}^{k}a_i^{b_i}\)
考虑换元 \(c_i = d_i-1\),原式变为:
\(\displaystyle \sum_{c_1+c_2+\cdots+c_k = k-2,\ c_i \ge 0} \begin{pmatrix} k-2 \\ c_1, c_2, \cdots, c_k \end{pmatrix} \prod_{i=1}^{k} s_i^{c_i+1}\)
\(\displaystyle = (s_1+s_2+\cdots+s_k)^{k-2} \prod_{i=1}^{k} s_i = (n^{k-2} \prod_{i=1}^{k} s_i)\)
事实上,这就是图连通方案数的公式
接下来,考虑一开始没有环的情况;此时,我们需选择一个连通块集 \(S\),将 \(S\) 内的连通块连成一个大奇环,再套用上述公式解决
首先,考虑分讨将 \(S\) 内的连通块连成大奇环的方案数:
-
\(|S| = 1\),设该连通块点数为 \(s\),边数为 \(e\),则方案数为 \(C_{s}^{2}-e\)
-
\(|S| = 2\),设两连通块点数为 \(s_1, s_2\),则方案数为 \(C_{s_1s_2}^{2}\) (不能连出重边)
-
\(|S| \ge 3\),此时无需考虑重边的问题;首先,每个连通块都要选 \(2\) 个点 (可重),方案数为 \(\prod_{i \in S} s_i^2\)
那么所有连通块排成了一个环;由于环上转圈 / 翻转是本质相同的,排成环的方案数即为 \(\displaystyle \frac{|S|!}{2|S|} = \frac{1}{2} (|S|-1)!\) (多除 \(2\) 是去掉翻转)
综上,总方案数为 \(\displaystyle \frac{1}{2} (|S|-1)! \prod_{i \in S} s_i^2\)
其次,考虑将 \(|S|\) 内的大奇环与其余连通块连成一棵树的方案数
由上述公式,这只与 \(\sum_{i \in S} v_i\) 有关;具体的,为 \(\displaystyle n^{k-|S|+1} (\sum_{i \in S} v_i) \prod_{i \notin S} s_i\)
因此,对于 \(|S| = 1\) 和 \(|S| = 2\) 的情况,我们可以直接 \(O(n^2)\) 枚举 \(S\) 中的连通块;下面只考虑 \(|S| \ge 3\) 的情况
将完整式子写出来,为 \(\displaystyle (\frac{1}{2} (|S|-1)! \prod_{i \in S} s_i^2)\ n^{k-|S|+1} (\sum_{i \in S} s_i) \prod_{i \notin S} s_i\);事实上,\(\displaystyle \prod_{i \notin S} s_i\) 也可以用 \(\displaystyle \prod_{i \in S} s_i\) 表示
设 \(\text{tot} = \prod_{i=1}^{k} s_i\);那么式子为 \(\displaystyle (\frac{1}{2} (|S|-1)! \prod_{i \in S} s_i)\ n^{k-|S|+1} (\sum_{i \in S} s_i) \ \text{tot}\)
注意到答案只与 \(\displaystyle |S|, \sum_{i \in S} s_i, \prod_{i \in S} s_i\) 有关;考虑对"确定 \(|S|\) 中连通块"的过程进行 DP,将 \(|S|\) 与 \(\displaystyle \sum_{i \in S} s_i\) 设为状态,对可能的 \(\displaystyle \prod_{i \in S} s_i\) 的和 DP 即可
直接做时间复杂度是 \(O(n^3)\),考虑优化状态;注意到 \(\displaystyle \sum_{i \in S} s_i\) 只作为乘积出现一次,考虑将其贡献分摊到加入的每个 \(s_i\) 身上
事实上,这也与我们枚举 \(s_i\) 选择是否加入的 DP 转移过程吻合
令 \(f_{i, j}\) 表示前 \(i\) 连通块,选择到 \(|S| = j\) 时,答案式的值
类似 \(01\) 背包,转移时每次拼上一个 \(s_i\);考虑对答案式中的值一个个分析其变化:
-
对于 \((|S|-1)!\),由于 \(|S| \leftarrow |S|+1\),需要多乘上 \(j-1\)
-
对于 \(\displaystyle \prod_{i \in S} s_i\),由于 \(S \leftarrow S \bigcup s_i\),需要多乘上 \(s_i\)
-
对于 \(n^{k-|S|+1}\),由于 \(|S| \leftarrow |S|+1\),需要多乘上 \(\frac{1}{n}\)
-
对于 \(\displaystyle \sum_{i \in S} s_i\),好像爆炸了;没关系,我们将加入 \(s_i\) 后的贡献分为两部分:
- 未加入 \(s_i\) 前的答案式,将其更新为 \(|S| \leftarrow |S|+1\) 的版本后,新的贡献
- 单独对于 \(s_i\),其乘上去掉求和部分的,未加入 \(s_i\) 前的答案式,带来的贡献
对于第二种情况,我们发现还需要设 \(g_{i, j}\) 表示前 \(i\) 连通块,选择到 \(|S| = j\) 时,除去求和部分的,答案式的值
事实上,将 \(g_{i, j}\) 更新为 \(|S| \leftarrow |S|+1\) 的版本时,方案与上述更新 \(f_{i, j}\) 方案基本相同
综上,对于 \(f_{i, j}\),其转移为:
-
不选 \(s_i\),转移为 \(f_{i, j} \leftarrow f_{i-1, j}\)
-
选 \(s_i\),对于之前的求和式带来的贡献,为 \(f_{i, j} \leftarrow f_{i-1, j-1} \times (j-1) \times s_i \times \frac{1}{n}\)
对于 \(s_i\) 单独带来的贡献,为 \(f_{i, j} \leftarrow g_{i-1, j-1} \times (j-1) \times s_i^2 \times \frac{1}{n}\)
对于 \(g_{i, j}\),其转移为:
- 不选 \(s_i\),转移为 \(g_{i, j} \leftarrow g_{i-1, j}\)
- 选 \(s_i\),转移为 \(g_{i, j} \leftarrow g_{i-1, j-1} \times (j-1) \times s_i \times \frac{1}{n}\)
对于初值,我们不考虑是否有实际意义,只考虑使定义式有意义;因此从 \(i = 1\) 开始赋 (照着定义式赋即可),从 \(i=2\) 开始转移
为什么对?由我们的推导过程,这么赋不影响中间 DP 值的正确性;而我们在计算答案时会把 \(j \le 2\) 的情况挖掉,因此没有实际意义的 DP 值也不会被计入答案
DP 部分答案即为 \(\displaystyle \sum_{i \ge 3} f_{k, i}\)
综上,DP 部分时间复杂度 \(O(n^2)\),总时间复杂度 \(O(n^2)\)
这道题启示我们:对于 \(01\) 背包中随物品加入简单变化,且与答案式有关的变量,可以将其贡献拆开到每次加入新物品时计算,而不必列入状态中
05.22 - 2.回滚
直接做没有前途,考虑换维
每次回滚会消去最近的未回滚的比赛,这与括号匹配很像;考虑将"比赛"看作带权的 (,"回滚"看作 ),答案即为未匹配的左括号的权值和
具体的,对于三种操作:
- "第 \(i\) 时刻,\(a_l\) 到 \(a_r\) 执行 \(+x\) "变成:\(l\) 时刻,在 \(a_i\) 加入权值为 \(x\) 的
(,在 \(r+1\) 时刻撤销 - "第 \(i\) 时刻,\(a_l\) 到 \(a_r\) 回滚"变成:\(l\) 时刻,在 \(a_i\) 加入
),在 \(r+1\) 时刻撤销 - "第 \(i\) 时刻,查询 \(a_p\)"变成:\(p\) 时刻,查询 \([1, i]\) 的括号序列中,未匹配的左括号的权值和
这么做的好处在于,每次修改都只对一个点操作
考虑上线段树维护区间括号序列;问题在于怎样 pushup
显然,最终每个节点一定形如 ))...)((...(;将两区间 \(l, r\) 合并时,只有 \(l\) 后面的左括号与 \(r\) 前面的右括号会发生抵消
因此,考虑在每个节点维护未匹配左括号个数 \(\text{lc}\),未匹配右括号个数 \(\text{rc}\),答案 \(w\);类似楼房重建,对于区间 \(l, r\),我们递归地 pushup:
-
记 \(l\) 的左区间为 \(ls\),右区间为 \(rs\);若 \(rs.lc \ge r.rc\),则 \(r.rc\) 不会对 \(ls.lc\) 产生影响;累加上 \(l\) 中去掉 \(rs\) 影响的答案,递归 \(rs, r\) 即可
-
反之,\(rs.lc\) 全部被消掉;递归 \(ls, r\) 即可;但此时 \(r.rc\) 也被消掉了一部分,不能再用 \(r.rc\) 代替,有问题
因此,我们在 pushup 过程中再维护变量 \(c\) 代表 \(r\) 中剩下的未匹配右括号个数即可
由于每次只会挑一边递归,时间复杂度 \(O(n \log^2 n)\)
这道题启示我们:区间加 + 区间回滚可采用如上做法;另外
- 可尝试换维以简化修改操作
- 维护括号序列 (配对括号会消除) 的相关信息,可考虑线段树 + 类楼房重建 pushup 方式
05.24 - 1.下雨
对于数 \(k\),我们定义其"最小阶乘表示" \(f(k)\),表示所有将 \(k\) 拆分为 \(k = a_1!+a_2!+\cdots+a_m!\ (a_i>1)\) 的方案中,最小的 \(\sum a_i\)
那么题意即为求最小的 \(k\),使得 \(f(k) > n\)
考虑观察一些 \(f(k)\) 的简单性质:
-
出现 \(\ge i+1\) 个 \(i!\) 必然不优,此时可将其合并为 \((i+1)!\),对 \(\sum a_i\) 的贡献显然更小
-
这启示我们将值相同的 \(i!\) 合并;那么形成了一个类似数位的东西,第 \(i\) 位的值代表 \(i!\) 填多少次,权为 \(i\)
不妨设第 \(i\) 位的值为 \(b_i\);由上述性质,必然有 \(b_i < i+1\)
-
-
由于希望 \(\sum a_i\) 最小,我们肯定先填满足 \(i! \le k\) 的最大的 \(i!\),再填 \((i-1)!\),以此类推
- 换句话说,对于任意数,其"最小阶乘表示"及其数位形式是唯一的,总是从合法的最高位逐渐向低填
-
显然有 \(f(k+1) \le f(k)+1\),在 \(f(k)\) 的方案中补一个 \(1!\) 即可
-
由这一性质,可将题意进一步转化为求最小的 \(k\),使得 \(f(k) = n+1\)
证明:反证,设 \(f(k) > n+1\),则 \(f(k-1) \ge f(k)-1 > n\),由 \(k\) 的最小性有 \(f(k-1) = n+1\),那么 \(k-1\) 更小且符合要求,证毕
-
综上,我们要求最小的 \(k\),使得其"最小阶乘表示"的数位形式下,\(\sum ib_i = n+1\)
既然要最小化 \(k\),高位的贡献又远大于低位,我们必定想在高位尽量少填;考虑贪心地从极端情况入手
- 将所有位全部填满,表示形式必为 \((i-1)(i-1)!+(i-2)(i-2)!+\cdots+1! = i!-1\) (归纳易得),此时 \(\sum ib_i = \sum i^2\)
因此,找到最大的 \(p\) 使得 \(1^2+2^2+\cdots+p^2 \le n+1\),我们从 \(p+1\) 向 \(1\) 贪心地填,具体的:
- 对于每位 \(i\),将 \(b_i\) 逐渐增大,直到 \(\sum_{j=i}^{p+1} jb_j+\sum_{j=1}^{i-1} j^2 \ge n+1\)
\(p\) 是 \(O(n^{\frac{1}{3}})\)级别的,直接贪时间复杂度为 \(O(Tn^{\frac{2}{3}})\)
考虑分析贪心实际上干了什么
在第一步,找到最大的 \(p\),我们暂时认为 \(\forall i \in [1, p]\),数位 \(i\) 上都填 \(i\);先贪心地确定 \(p+1\) 位上填什么,设为 \(c\)
注意到:\(\sum_{j=1}^{p} j^2+c(p+1) - (n+1) < p+1\)
证明:由于 \((i-1)(i-1)!+(i-2)(i-2)!+\cdots+1! = i!-1\),把低位全部填满也补不上高位一个 \(1\),若多差一个 \(p+1\) 就补不回来了
不妨设上式的值为 \(p'\);那么在 \(>p'\) 的位上减就减多了,因此刚好会在 \(p'\) 位上 \(-1\);此时 \(\sum_{j=1}^{p+1} jb_j\) 也·恰好为 \(n+1\)
神奇的事情发生了:你已无需进行任何其他修改,已经达到最优方案了
那么模拟一下算出来就好了,时间复杂度 \(O(T \log n)\)
这道题启示我们:从极端情况考虑,同时可以考虑模拟贪心策略干了什么,可能可以直接模拟解决
05.24 - 2.沙尘暴
由绝对值函数的凸性,对于从点 \(i\) 向外走的一段连续的点,必将其高度全部调整为这段点中某个点的高度
那么,我们可以将由 \(s\) 到 \(t\) 的最短路分为如下几部分:
- 从 \(s\) 走到 \(u_1\),将经过的点的高度 (包括起终点) 全部改为 \(h_{u_1}\)
- 从 \(u_1\)走到 \(u_2\),将前一段点的高度全部改为 \(h_{u_1}\),后一段点的高度全部改为 \(h_{u_2}\)
- 从 \(u_2\) 走到 \(u_3\),……,从 \(u_{k-1}\) 走到 \(u_k\),策略同上
- 从 \(u_k\) 走到 \(t\),将经过的点的高度 (包括起终点) 全部改为 \(h_{u_k}\)
考虑先跑 \(n\) 遍 dij,求出以点 \(i\) 为起点,走到 \(j\),将经过的点的高度全部改为 \(h_i\) 的贡献 \(f_{i, j}\)
此时,我们可以求出路径中从 \(u_i\) 走到 \(u_{i+1}\) 的贡献;具体的:
- 枚举中转点 \(v\),对 \(f_{u_i, v}+f_{u_{i+1}, v}+C|h_{u_i}-h_{u_{i+1}}|-d_v|h_{u_{i+1}}-h_v|\) 取 \(\min\) 即可 (多减一个是因为 \(d_v\) 被多改了一次)
设这个贡献为 \(g_{i, j}\)
接下来,考虑求出从以点 \(i\) 为起点,走到点 \(j\) 的贡献 (可能包含一个 \(f_{i, j}\) 与若干 \(g_{i, j}\) );直接 \(n\) 次 dij,边权视为 \(g_{i, j}\) 即可
设这个贡献为 \(p_{i, j}\);注意,进行 dij 前数组是有初值的,由定义,\(p_{i, j} \leftarrow f_{j, i}\)
同理,\(n\) 次 dij 求出以点 \(i\) 为终点,从 \(j\) 走过来的贡献;设这个贡献为 \(q_{i, j}\)
对于答案,设起点为 \(s\),终点为 \(t\),枚举中转点 \(v\),对 \(p_{s, v}+q_{t, v}\) 取 \(\min\) 即可
时间复杂度 \(O(n^3)\)
这道题启示我们:可以考虑将复杂的路径拆分成几段,对每段分别求解后拼起来
06.01 - 2.王之抽签
容易发现,只要有能拿到的 \(+1\),小 W 总是能拿到;于是无解条件为:
- 对每堆数选择一个前缀 \(p_i\),满足 \(\sum_{i=1}^{n} \sum_{j=1}^{p_i} = 1\)
- 对每堆数,都有 \(a_{i, p_i+1} = -1\) 或 \(p_i = m_i\) (取空了)
- 至少有一堆数,满足 \(p_i < m_i\) (不能全取空了)
考虑先对每堆数填数的方案数进行 DP,再进行整体的背包
具体的,设 \(f_{i, j}\) 表示第 \(i\) 堆数,填数后满足 \(\displaystyle (\min_{p_i} \sum_{k=1}^{p_i} a_{i, k}) = j\) 且满足限制 \(2\) 的方案数
为什么是 \(\min\)?因为对每堆数,我们都按照最劣情况进行;若全部按照最劣情况进行时,仍有限制 \(1\) 中和式 \(>0\),那么必然有解
求出 \(f_{i, j}\) 后,对其进行背包;具体的,设 \(dpf_{i, j}\) 表示前 \(i\) 堆数,每个前缀和的和为 \(j\) 的方案数,则 \(\sum_{j>0} dpf_{n, j}\) 即为答案 (别忘了小 W 自己初始为 \(+1\))
不过现在我们没有考虑限制 \(3\);被漏掉的一种情况是限制 \(1\) 中和式为 \(0\),且每堆数刚好取完
那么设 \(g_{i, j}\) 表示第 \(i\) 堆数,填数后满足 \(\displaystyle (\min_{p_i} \sum_{k=1}^{p_i} a_{i, k}) = j\) 且满足限制 \(2\) 的方案数,且唯一最小值取在 \(p_i = m_i\) 的方案数
为什么要求唯一?因为若不唯一,限制 \(1\) 中和式为 \(0\),在第一次在前面取到最小值时就不成立了
那么类似的设 \(dpg_{i, j}\),表示只对 \(g_{i, j}\) 的背包,\(dpg_{n, 0}\) 即为漏掉的方案数
现在问题只在于求 \(f_{i, j}\) 与 \(g_{i, j}\):
-
对于 \(f_{i, j}\),对第 \(i\) 堆数,朴素的想法是设 \(dp_{i, j, k}\) 表示从前往后考虑到第 \(i\) 位,前缀和为 \(j\),前缀和的 \(\min\) 为 \(k\) 的方案数
转移是容易的;时间复杂度 \(O(n^3)\)
考虑从后向前 DP;这样的好处是每加入一个数,相当于在所有的前缀和上都拼上一个数,这样就无需单独记当前前缀和大小
设 \(dp_{i, j}\) 表示从后向前考虑到第 \(i\) 位,前缀和 (以 \(i\) 为起点) 的 \(\min\) 为 \(j\) 的方案数:
- 若 \(a_{i, j}\) 填 \(+1\),转移为 \(dp_{i, j} \leftarrow dp_{i, j-1}\)
- 若 \(a_{i, j}\) 填 \(-1\),还需要判断 \(j\) 与 \(0\) 的大小关系:
- \(j > 0\),不成立,因为此时前缀和的 \(\min\) 至少为 \(0\) (取空前缀)
- \(j < 0\),转移为 \(dp_{i, j} \leftarrow dp_{i, j+1}\)
- \(j = 0\),只能由之前"前缀和的 \(\min\) 取值 \(>0\)" 的情况转移而来 (否则减一下更小),转移为 \(dp_{i, 0} \leftarrow dp_{i, j},\ (j>0)\)
-
对于 \(g_{i, j}\),转移类似,只不过 \(j=0\) 时不成立 (因为不是唯一取值)
时间复杂度 \(O(n^2)\),有亿点卡常
这道题启示我们:处理前缀和相关 DP,可以从后向前考虑

浙公网安备 33010602011771号