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 值域

待补:

连通性问题

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\) 的最短路,考虑把这五个点拎出来;由于是竞赛图,两点间必有边,又不能产生更短的路径,于是其余边的方向均确定

1

(来自 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 总是能拿到;于是无解条件为:

  1. 对每堆数选择一个前缀 \(p_i\),满足 \(\sum_{i=1}^{n} \sum_{j=1}^{p_i} = 1\)
  2. 对每堆数,都有 \(a_{i, p_i+1} = -1\)\(p_i = m_i\) (取空了)
  3. 至少有一堆数,满足 \(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,可以从后向前考虑

posted @ 2025-06-12 21:29  lzlqwq  阅读(48)  评论(0)    收藏  举报