2025.9 做题记录

2025.9 做题记录

9.1 - 9.3

网课 + 补暑假作业 + 摆烂

但是再不努力就没有机会了。

9.4

QOJ7999 拉丁方 (二分图边染色)

部分分:\(C = n\)

考虑将每列缩成一个点,若列与数字不冲突则在列与数字间连边;显然会形成一个左部点为列,右部点为数字的二分图

现在我们希望进行 \(n-R\) 次操作,每次找到一组完美匹配并删去

首先考虑是否有解:

  • 容易发现,左部点的度数均为 \(n-R\);每个数字在上面 \(R \times n\) 的矩阵中恰出现 \(R\) 次,右部点的度数也均为 \(n-R\)

    对于每个点度数均为 \(k\) 的图,我们称为 \(k\) - 正则图

  • 对于 \(k\) - 正则图,由 Hall 定理,必存在一组完美匹配

  • 将完美匹配删去,会形成 \(k-1\) - 正则图;那么归纳可得必存在 \(k\) 组完美匹配

    综上,原问题有解

考虑如何解决原问题:

  • 事实上,这是二分图边染色问题

    我们需要给二分图中的每条边染色,使得同色边不共顶点

  • 有结论:记最大度数为 \(\text{deg}\),则最少只需 \(\text{deg}\) 种颜色即可

    显然,顶点的每条出边颜色不能相同,\(\text{deg}\) 是答案的下界

    接下来考虑给出构造

    考虑依次加入每条边;设当前加入 \((u, v)\),我们维护每个顶点已染出边颜色的 \(\text{mex}\)

    • \(\text{mex}_u = \text{mex}_v\),则将 \((u, v)\) 染成 \(\text{mex}_u\) 即可

    • 反之,令 \((u, v)\) 的颜色为 \(\text{mex}_u\)

      \(v\) 已有颜色为 \(\text{mex}_u\) 的出边,记为 \((v, v')\),考虑将 \((v, v')\) 的颜色调整为 \(\text{mex}_v\)

      \(v'\) 之前已有颜色为 \(\text{mex}_v\) 的出边,记为 \((v', v'')\),考虑将 \((v', v'')\) 的颜色调整为 \(\text{mex}_u\)

      \(v''\) 之前已有颜色为 \(\text{mex}_u\) 的出边,记为 \((v'', v''')\),考虑将 \((v'', v''')\) 的颜色调整为 \(\text{mex}_v\)

      综上,类似增广路,依次将冲突边的颜色调整为 \(\text{mex}_u, \text{mex}_v, \text{mex}_u, \text{mex}_v, \cdots\)

      容易证明,最终不会调整回 \(u\)

      由于我们总是照着 \(\text{mex}\) 调整的,最终答案不会超过 \(\text{deg}\);证毕

那么直接模拟二分图边染色即可;单次最劣时间复杂度 \(O(n^3)\)

接下来考虑原问题

部分分启示我们先填上面的 \(R \times (n-C)\),再填剩下的 \((n-R) \times n\)

对于上面的部分,将行与数字连边,容易发现仍为二分图边染色

但此时整个二分图不是 \(k\) - 正则图,令最大度数为 \(\text{deg}\)

  • \(\text{deg} = n-C\),直接二分图边染色即可
  • \(\text{deg} > n-C\),所需颜色数必然 \(>n-C\),无法找出 \(n-C\) 组最大匹配,无解

判掉无解的情况后跑两次二分图边染色即可;总时间复杂度 \(O(Tn^3)\),实际上跑不满

实现时可能需要对加边顺序 random_shuffle 防止被卡满

9.5

P3623 [APIO2008] 免费道路 (最小生成树 - 限制特殊边数量)

以下称"鹅卵石路"为"黑边","水泥路"为"白边"

注意到对所有黑边,有些是必连的 (否则不连通),有些是可连可不连的

考虑先求出必连边

先将所有白边加上,跑一遍 Kruskal,此时选中的黑边即为必连边

容易发现若有多条黑边满足要求,随便选不影响答案

考虑确定可连可不连的边

将必连边都连上后跑 Kruskal,优先连黑边,直到连够 \(K\) 条为止

无解情况:图不连通 / 必连边个数 \(>K\) / 按如上方式构造出的最终方案中黑边个数 \(<K\)

时间复杂度 \(O(\alpha m)\)

9.6

摆烂 + 补 whk

9.7

模拟赛

9.7 T1 - CF1527D - MEX Tree (往大容斥 + 分讨)

看到这个形式,首先考虑容斥

注意到往小容斥 (转化为 \([\text{mex} \le k]-[\text{mex} \le k-1]\) ) 是不好做的,考虑往大容斥

对于 \([\text{mex} > k]\),相当于强制加入点 \(0 \sim k\),再随意选点形成路径

从小到大依次加入点 \(0 \sim n\),考虑维护路径端点 \(u, v\)

只需分讨两端点是否有祖先关系即可;若加入点后无法形成路径,则后面的答案都是 \(0\)

时间复杂度 \(O(n \log n)\)

反思:

  • 场上在往小容斥的思路里陷的太深了,花了 1h 才意识到往大容斥直接做完了,以后应该两种方向都想下

    需要锻炼做简单题的速度,1h30min 才切 T1 根本没可能切出 T3, T4,只能拿大众分

9.7 T2 - CF1497E2 - Square-free division (hard version) (DP 优化 - 先枚举值域小维 + 贪心选择转移区间 + 消平方因子)

首先显然有 \(O(n^2k)\) 的 DP

\(f_{i, j}\) 表示到第 \(i\) 位用了 \(j\) 次修改,能划分出的最少连续段数

转移为 \(f_{i, j} \leftarrow f_{k, j-w(k+1, i)}\),其中 \(w(l, r)\) 表示将 \(a_{[l, r]}\) 改到合法的最小修改次数

考虑如何求出 \(w(l, r)\)

对于一次修改,我们可以把一个数改成极大质数,使其不与任何数冲突

将区间内的冲突关系连边,容易发现形成了很多完全图;对大小为 \(siz\) 的完全图,只需改 \(siz-1\) 次即可

由于是完全图,只需维护每个点向前 / 向后的第一次连边即可

\(O(n^2)\) 预处理出 \(w(l, r)\),DP 转移是 \(O(n^2k)\)

考虑对 DP 进行优化

对于 \(O(n^2k)\) 的转移,问题在于我们每次先枚举上个区间的结束位置 \(k\);注意到第二维值域是 \(K\),考虑先枚举第二维

具体的,钦定 \(w(l, r) = v\),我们先枚举 \(v\);有一个显然但重要的性质是若 \(r, v\) 确定,\(l\) 越靠前越好

因此,转移区间只有 \(K\) 个,直接转移是 \(O(nk^2)\) 的,可以接受

现在的问题是如何求出 \(l_{r, v}\),表示最靠前的使得 \(w(l, r) = v\)\(l\)

一切的基础在于,我们需要先求出每个点向前 / 向后的第一次连边

一个常见的 Trick 是消平方因子,消完后 \(a_l, a_r\) 有连边等价于 \(a_l = a_r\)

一种想法是线段树上二分

具体的,从左往右扫,设当前扫到 \(i\),其向前的第一次连边是 \((\text{ls}_i, i)\),将 \([1, \text{ls}_i]\) 区间加 \(1\)

枚举 \(v\),线段树上二分左端点即可;时间复杂度 \(O(nk \log n)\)

更厉害的做法是,你注意到当 \(v\) 不变且 \(r\) 变大时,\(l_{r, v}\) 也会变大,换句话说是有单调性的

那么直接双指针即可;时间复杂度 \(O(nk)\)

综上,预处理时间复杂度 \(O(nk)\),DP 时间复杂度 \(O(nk^2)\),可以通过

反思:

  • 对于 \(f_{i, j} \leftarrow f_{k, j-w(j+1, i)}\) 这种类划分区间转移,当第二维值域较小,可以考虑先枚举第二维 + 观察性质以优化复杂度

    需要注意不能在贪心上陷太久;动态维护最多覆盖位置一般是没啥道理的

  • 已经做过的 Trick 不应该想不起来的;尤其是忘记了消平方因子,第一步不会啥都没法做了

9.7 T3 - CF1536F - Omkar and Akmar (观察性质)

诈骗题

注意到 AB 必然成对出现,由于是环,最后必然进行偶数步

因此显然有后手必胜,且不管怎么填都没事

那么问题转化为对合法游戏过程计数

枚举空格数 \(i\),显然不能有 \(\ge 2\) 个空格相邻,考虑插板法

\(n-i\) 个数字排成一排,首尾的空是相同的,方案数为 \(\binom{n-i}{i}\);乘上将数字填进去的圆排列数,即 \(\times (n-i-1)!\)

每个空有 ABA...BAB... 两种填法,需要 \(\times 2\);环上可以随意旋转,需要 \(\times n\)

那么最终式子即为 \(\displaystyle 2n \sum_{i = n \bmod 2, i \leftarrow i+2}^{\lfloor \frac{n}{2} \rfloor} \binom{n-i}{i} (n-i-1)!\)

反思:All you need is attention

9.7 T4 - 牛客多校 - Diameter Counting (DP - 直径转中点中边)

题意:求大小为 \(n\) 的所有带标号无根树的直径的和,答案对 \(P\) 取模

\(n \le 500\)\(10^8 \le P < 2^{31}\)

考虑直径的性质:长为奇数的直径都交于直径中边,长为偶数的直径都交于直径中点;考虑以中边 / 中点为根

因此,只需计数点数与最大深度固定的有标号有根树即可;考虑容斥解决

\(f_{i, j}\) 表示 \(i\) 个点,最大深度 (点数) \(\le j\) 的有标号有根树的数量

这里之所以用点数,是因为若用边数,不好区分没有点和只有一个点的情况

为方便转移,再令 \(g_{i, j}\) 表示 \(i\) 个点,最大深度 (点数) \(\le j\) 的有标号叶向森林的数量;特别的,只有一棵树也合法

考虑 \(f_{i, j}\)\(g_{i, j}\) 如何转移

\(f_{i, j}\),显然有 \(f_{i, j} \leftarrow g_{i-1, j-1} \times i\),表示选定一个根

\(g_{i, j}\),考虑枚举一个子树拼到森林中;但直接转移显然会算重

这里有个 Trick,我们钦定标号最小点必定在靠前的子树中,只重新分配剩余的 \(i-1\) 个标号,这样就能够避免算重

具体的,有转移 \(\displaystyle g_{i, j} \leftarrow \sum_{k=1}^{i} \binom{i-1}{k-1} f_{k, j} g_{i-k, j}\);枚举到 \(i\) 是因为单独一棵树也有贡献

\(f_{i, j}\)\(g_{i, j}\) 进行差分,差分数组记为 \(cf_{i, j}\)\(cg_{i, j}\),表示深度固定时的答案

考虑枚举直径长度 (边数) \(d\),按奇偶分类讨论:

  • \(d\) 为奇数,此时以边为根,两边连接两个子树;枚举子树大小即可

    贡献为 \(\displaystyle d \sum_{i=1}^{n-1} \binom{n-1}{i-1} cf_{i, \frac{d}{2}+1} cf_{n-i, \frac{d}{2}+1}\)

  • \(d\) 为偶数,此时以点为根,可连接多个子树,限制至少两个子树的最大深度为 \(\frac{d}{2}\)

    考虑用 \((cg_{n-1, \frac{d}{2}}-cf_{n-1, \frac{d}{2}}) \times n\),森林 (不能是一棵树) + 选定根解决

    但这个式子的意义是每棵子树的深度都是 \(\frac{d}{2}\);我们只要求至少两棵是 \(\frac{d}{2}\),因此考虑容斥解决

    具体的,先用 \((g_{n-1, \frac{d}{2}}-f_{n-1, \frac{d}{2}})-(g_{n-1, \frac{d}{2}-1}-f_{n-1, \frac{d}{2}-1})\) 算出有的深度是 \(\frac{d}{2}\),有的是 \(\frac{d}{2}-1\) 的数量

    考虑再减去只有一棵深度为 \(\frac{d}{2}\) 的数量

    强行钦定一棵子树深度为 \(\frac{d}{2}\),方案数为 \(\displaystyle \sum_{i=1}^{n-2} \binom{n-1}{i} cf_{i, \frac{d}{2}} cg_{n-1-i, \frac{d}{2}-1}\)

    注意,这里组合数是 \(\binom{n-1}{i}\) 而非 \(\binom{n-2}{i-1}\),因为此处将特殊子树插到哪里都行,不需要钦定一定在最前面

    那么总式子为 \(nd \times [(g_{n-1, \frac{d}{2}}-f_{n-1, \frac{d}{2}})-(g_{n-1, \frac{d}{2}-1}-f_{n-1, \frac{d}{2}-1})-\displaystyle \sum_{i=1}^{n-2} \binom{n-1}{i} cf_{i, \frac{d}{2}} cg_{n-1-i, \frac{d}{2}-1}]\)

    此处多乘 \(n\) 是因为还需要钦定根

时间复杂度 \(O(n^3)\);轻微卡常,精细实现取模与枚举上下界就能过

实现时注意:

  • 没有保证 \(P\) 是质数,不能用阶乘 + 逆元的方式求组合数,写递推即可
  • 根据实现不同,可能需要在转移式中的一些地方让第二维对第一维取 \(\min\)

反思:

  • 统计直径时考虑转化为以直径中点 + 直径中边为根,再对树 / 森林计数
  • 想清楚细节再写!手玩小数据确实是很好的检查细节的办法

9.9

CF888G - Xor-MST (最小生成树 - B + 01Trie 分治)

法 1

对于完全图生成树,考虑 Boruvka

现在的问题是如何快速求出一个连通块 \(S\) 向外部点的最小连边

对于异或,考虑 01 Trie

维护连通块的 Trie 与全局 Trie,对每个点维护 \(\text{siz}\),合并时枚举连通块内每个点,在全局字典树中将 \(\text{siz}\) 对位减后查询即可

时间复杂度 \(O(n \log n \log V)\)

法 2

考虑分治,每次将当前点集 \(S\) 分为两个集合 \(L, R\),递归处理 \(L, R\),再在两个点集中各选一点连边

分治时传参数 \(\text{bit}\),每层分治按当前数的第 \(\text{bit}\) 位分类

正确性证明:

  • 若将 \(0\) 集合中的点 \(a_i\) 放入 \(1\) 集合 (反过来同理):

    • \(a_i\)\(0\) 集合连边,本质上与 \(a_i\) 本来就在 \(0\) 集合没有区别
    • 反之,则此时代价至少为 \(2 \times 2^{\text{bit}} = 2^{\text{bit}+1}\) ( \(1\) 集合内向 \(a_i\) 连,\(1\) 集合内向 \(0\) 集合连)
  • 若不将 \(0\) 集合中的点放入 \(1\) 集合,当前层代价为 \(2^{\text{bit}}\) ( \(1\) 集合内向 \(0\) 集合连)

    类似的,往下分治后的代价最大为 \(2^0 + 2^1 + \cdots + 2^{\text{bit}-1}\)

    那么总代价为 \(2^0 + 2^1 + \cdots + 2^{\text{bit}} = 2^{\text{bit}+1}-1\)

综上,\(2^{\text{bit}+1}-1 < 2^{\text{bit}}\),证毕

实现时,先递归左侧,递归不下去时将当前数插入 Trie 中,再枚举右侧点放在 Trie 中查询;最后递归右侧即可

时间复杂度 \(O(n \log n \log V)\)

CF1305G - Kuroni and Antihype (刻画答案 + 建虚点 + 重标边权 + 最小生成树 - 枚举边权)

将邀请关系连有向边,容易发现形成了多个 DAG;此时答案为 \(\displaystyle \sum_{u} a_u \text{out}_u\)

建立点 \(n+1\),满足 \(a_{n+1} = 0\);对所有通过方式 \(1\) 加入的点 \(u\) 连边 \(n+1 \rightarrow u\);这样保证最终只有一个 DAG

DAG 是不好办的,我们希望将有向边转为无向;注意到一个点入度最多为 \(1\),考虑重赋边权

\((u, v)\) 的边权重置为 \(a_u+a_v\),最终再减去 \(\displaystyle \sum_{u} a_u\) 即可;此时形成了树

那么我们只需求解最大生成树即可

枚举边时间复杂度无法接受;注意到同边权的边会连很多条,考虑 Kruskal,转为枚举最大边权 \(w\)

对于边 \((u, v, w)\),必然有 \(a_u\)\(a_v\) 按位与为 \(0\);因此加可转化为按位或,一个很好的性质是 \(a_v = w \oplus a_u\)

综上,枚举 \(w\),再枚举 \(w\) 的子集 \(u\),维护相同值的连通块个数 \(\text{cnt}_u\),合并 \(u\)\(w \oplus u\)

具体的,合并 \(w, u, v\) ( \(w \oplus u = v\) ) 时,贡献为 \(w \times (\text{cnt}_{\text{fa}_u}+\text{cnt}_{\text{fa}_v}-1)\);合并后的新连通块的根的 \(\text{cnt} = 1\)

时间复杂度 \(O(3^{\log V} \alpha(n))\)

9.10

P3206 [HNOI2010] 城市建设,但是没调出来

9.11

P3206 [HNOI2010] 城市建设 (cdq / 线段树分治 + 观察性质 + 可撤销并查集)

对于永久修改操作,考虑 cdq / 线段树分治动态转静态,两者本质相同,此处以 cdq 为例

令当前分治区间为 \([l, r]\),表示求解前 \(i\ (i \in [l, r])\) 个操作的答案

称操作 \([l, r]\) 中修改的边为 "动态边",其余边为 "静态边"

\(\text{len} = r-l+1\),我们希望将每层 cdq 的复杂度控制在 \(O(\text{len} \log \text{len})\) 以内

考虑观察性质:

  • 若强制不连动态边,跑最小生成树,此时仍不在最小生成树中的边肯定用不到,可以扔掉
  • 若强制连动态边,跑最小生成树,此时仍在最小生成树中的边肯定会用到,可以直接缩起来

因此,考虑在每层维护可能用到的静态边集合 \(S\)

当往 \([l, \text{mid}]\) 递归时,流程如下:

  • \([\text{mid}+1, r]\) 为静态边 (若与 \([l, \text{mid}]\) 中的边冲突则扔掉),加入集合 \(S\)

  • \(S\) 跑 Kruskal,记最小生成树边集为 \(T\),令 \(S \leftarrow T\);最后将并查集撤销回初始状态

  • \([l, \text{mid}]\) 这些动态边缩起来,再对 \(S\) 跑 Kruskal,记最小生成树边集为 \(T\);将并查集撤销回初始状态

    \(T\) 中的边直接缩起来,更新答案,递归 \([l, \text{mid}]\);回溯时记得把答案减回来、并查集撤回来

  • 当要求解 \([\text{mid}+1, r]\) 时,\([l, \text{mid}]\) 的边已经成为了静态边

    对于这些边,若不与 \([\text{mid+1}, r]\) 中的边冲突,则要加入 \(S\)

  • 同理,进行删无用静态边、缩必需静态边的操作,更新答案,递归 \([\text{mid}+1, r]\);回溯时同样减答案、撤并查集

边界为 \(l = r\) 时,设当前动态边为 \((u, v)\)

  • \(u, v\) 已经连通,只需更新当前边最新权即可

  • \(u, v\) 不连通,则可选择连动态边 / 连 \(S\) 中的一条边

    在两种情况中取 \(\min\) 并更新答案,同时更新当前边最新权即可

初始时,静态边集为未被修改操作覆盖的边;我们需要先进行一次删无用静态边、缩必需静态边并更新答案的操作

实现时需要维护一个全局可撤销并查集:

  • \(\text{merge}\) 操作为 \(\text{siz}_u \leftarrow \text{siz}_u + \text{siz}_v\)\(\text{fa}_v = u\)

    开一个栈,在 \(\text{merge}\) 时记录修改信息,即 \(v, \text{siz}_v\)

  • 在撤销时,令 \(\text{siz}_{\text{fa}_v} \leftarrow \text{siz}_{\text{fa}_v}-\text{siz}_v\)\(\text{fa}_v = v\) 即可

  • 注意,可撤销并查集不能路径压缩 (不然不好撤销),只能按秩合并

时间复杂度 \(O(n \log^2 n)\)

实现时可能需要特判重边

9.12

P9531 [JOISC 2022] 复兴计划 (MST - 观察绝对值函数性质 + 拆贡献)

题意:给定无向连通图,边有边权,多次询问给定 \(x\),边权修改为 \(|w-x|\) 时的最小生成树边权和

\(n \le 500\)\(m \le 10^5\)\(q \le 10^6\)

考虑观察绝对值函数的性质

将所有 \(f_i(x) = |w_i-x|\) 画在平面直角坐标系中,会形成许多 V 形

9.13

摆烂 + 补 whk

9.14

模拟赛

9.14 T1 - 猜数 (数位 DP - 两位两位填)

考虑数位 DP

传统数位 DP 是一位一位确定的,注意到此处因为有 "翻转",前后两位相互对应,考虑两位两位的填

注意到位数对对应关系有影响,不过设 \(z\) 的位数为 \(\text{cnt}\),填的数只能为 \(\text{cnt}\) 位或 \(\text{cnt}-1\) 位,分别处理即可

由于是加法,进位最多只有 \(1\),考虑在状态中维护高低两处的进位

具体的,令 \(f_{i, 0/1, 0/1}\) 表示从前往后考虑到 \(a_i, a_{cnt-i+1}\) 这对数,高侧是否有向高的进位,低侧是否有从低进过来的位

转移时,将相加后两处的值写出来,枚举两位分别填的数 check 一下即可

边界条件为填到中心时,根据奇偶分讨,枚举两数 check 即可

细节上,注意可能有 \(9+1 \rightarrow 0\) 的情况,以及第一位不能填前导 \(0\)

时间复杂度 \(O(4T \log V)\)

反思:想清楚细节,优先找简单的方式实现,不要写着写着又推翻重写;做这种简单题的速度需要加强

9.14 T2 - 排序 (序列转环 + DS)

法 1

注意到,题目描述的排序过程实际上是不断找出未排好序的数的最大值,并换到最前面

这启示我们对每轮的最大值拆贡献

设当前最大值为 \(\text{mx}\),易得每次会将 \(\text{mx}\) 前未排好序的部分整体平移至序列最后 (不改变相对顺序)

考虑平衡树维护平移 + 查最大值 + 删数

具体的,对平移操作,考虑按 siz 分裂后交换左右儿子

对查最大值的操作,考虑线段树的思想,自底向上 pushup

时间复杂度 \(O(n \log n)\)

法 2

注意到,整体平移等价于在环上操作

那么我们只需维护在环上跳最大值的过程

一种想法是用线段树维护最大值 + 区间内未删的数的个数,时间复杂度 \(O(n \log n)\)

事实上,用线段树维护最大值是不必要的,因为我们每个数都会跳到

离散化后开 vector 记录每个数的出现位置,切换 vector 时二分即可

那么只需支持单点打 tag + 区间查打 tag 点的个数 (单点改区间查),树状数组即可

时间复杂度 \(O(n \log n)\),常数较小

反思:

  • 序列转环的 trick 需要积累
  • 平衡树是可以同时支持下标相关 + 值相关操作的,只不过不能直接按值分裂,需要用线段树的思想
  • 即使是非常小的转化也要先确认正确性,最好不要凭直觉;赛时因为第一步的错误转化浪费了大量时间

9.14 T3 - 水池 (笛卡尔树 + 贪心 - 每次选最优叶子)

将每个横线看成点,为保证高度连续,按其 \(y\) 坐标建笛卡尔树

设点 \(i\) 对应横线的宽度为 \(\text{wid}_i\),高度为 \(h_i\)

那么点 \(i\) 相对其父亲 \(\text{fa}_i\) 能多积的水量就是 \(\text{wid}_i \times (h_i-h_{\text{fa}_i})\),记为 \(w_i\)

首先考虑 \(k = 1\),即我们需要选择一个叶子

容易发现叶子 \(u\) 的贡献为其到根链上的 \(w_i\) 之和,记为 \(\text{dis}_u\);那么答案即为 \(\max \text{dis}_u\)

考虑解决原问题

\(k = 1\) 的情况启示我们,每次选择 \(\text{dis}_u\) 最大的叶子,刨去其对其他叶子的影响,重复 \(k\) 次即可

证明需要用到闵可夫斯基和;暂时咕咕咕

注意到每个点只会被清零一次,考虑每次暴力跳父亲,将链改转化为子树改;线段树维护即可

时间复杂度 \(O(n + k \log n)\)

反思:All you need is attention

9.14 T4 - 连线 (卡特兰数 + 括号树 + 树形 DP - 维护总覆盖长度)

先考虑 \(k = 0\) 的部分分

\(f_i\) 表示 \(i\) 个点的连线方案

转移时枚举第 \(i\) 个点向前连到哪个点,即 \(f_i \leftarrow f_{j-1} \times f_{i-j-1}\)

注意到这就是卡特兰数,记为 \(H_n\);对 \(n\) 个点的情况,若 \(n\) 为奇数则答案为 \(0\),反之为 \(H_{\frac{n}{2}}\),以下记为 \(C_n\)

从简单情况入手,考虑 \(k=1\) 的情况

若擦掉红线,贡献为 \(C_n\)

反之,考虑将红线两侧的点拼起来,再乘上红线内部点的贡献;记红线覆盖了 \(\text{len}\) 个点 (包括端点),贡献为 \(C_{n-\text{len}} \times C_{\text{len}-2}\)

考虑将其推广到 \(k\) 条互不相交的红线的情况

设第 \(i\) 条红线覆盖 \(\text{len}_i\) 个点

若留下的红线集合为 \(S\),贡献即为 \(C_{n-\sum_{i \in S} \text{len}_i} \times \prod_{i \in S} (\text{len}_i-2)\)

连乘部分可以拆到每次选择红线时计算,我们只关心 \(\sum_{i \in S} \text{len}_i\)

这启示我们将它刻画到 DP 状态中

考虑解决原问题

建出红线对应的括号森林 (区间完全包含则连边),考虑树形 DP

\(f_{u, x}\) 表示点 \(u\) 子树中上式为 \(x\) 的方案数,\(\text{len}_u\) 表示 \(u\) 对应括号的长度

\(u\) 内部小括号的贡献,有转移 \(f_{u, x} \leftarrow f_{u, k} \times f_{v, x-k}\ (v \in \text{son}_u)\),即树上背包

对外侧大括号内未被覆盖的点的贡献,有转移 \(f_{u, \text{len}_u} \leftarrow f_{u, i} \times C_{\text{len}_u-2-i}\)

为方便统计答案,设存在一个编号为 \(0\),覆盖 \([0, n+1]\) 的括号,作为括号树的根

答案即为 \(\sum_{i = 0}^{n} f_{0, i} \times C_{n-i}\);初始值为对每个点 \(u\),有 \(f_{u, 0} = 1\)

时间复杂度 \(O(n^2)\)

反思:由部分分推性质,逐步思考正解

9.15

P2934 [USACO09JAN] Safe Travel G (最短路树 + 树剖)

由于最短路唯一,考虑建出最短路树;最后即询问对每个点 \(u\),断掉 \((u, \text{fa}_u)\) 后的最短路长度

显然,选两条非树边是不优的

枚举每条非树边 \((u_i, v_i, w_i)\),考虑其对树上节点答案的影响

事实上,这条非树边只会影响满足如下条件的点:

  • \(u_i\)\(v_i\) 的到根链中
  • 子树中不同时包含 \(u_i\)\(v_i\)

对点 \(k\),该条边的贡献为 \(\text{dis}_{u_i}+\text{dis}_{v_i}+w_i-\text{dis}_k\)

注意到 \(\text{dis}_{u_i}+\text{dis}_{v_i}+w_i\) 与点的信息无关,设为 \(W_i\)

那么对点 \(k\),答案即为 \(-\text{dis}_k+\min W_i\)

树剖维护即可,时间复杂度 \(O(m \log^2 n)\)

P5100 [JOI 2017 Final] 足球 / Soccer (观察性质 + 拆点建图)

首先,一名球员必只在一段区间中控球,不可能传出去又接回来 (不然不如自己控球到对应位置)

因此,当球落地,我们总是会让离球最近的人去接

将每个位置拆成三个点,分别代表球落地 / 前后飞 / 左右飞,以下记为 \((x, y, 1/2/3)\)

对踢球操作,我们将 \(A \cdot p\) 的贡献刻画到空中,将 \(B\) 刻画到踢球时刻,具体的:

  • 连边 \(((x, y, 2), (x', y', 2), A)\),刻画前后飞
  • 连边 \(((x, y, 3), (x', y', 3), A)\),刻画左右飞
  • 连边 \(((x, y, 1), (x, y, 2/3), B)\),刻画踢球时刻

对运球操作,四连通连边即可,即 \(((x, y, 1), (x', y', 1), C)\)

对跑动 + 接球操作,考虑预处理出离 \((x, y)\) 最近的球员跑过去的贡献 \(w_{x, y}\),连边 \(((x, y, 2/3), (x, y, 1), w_{x, y})\)

预处理可以 bfs,这部分时间复杂度 \(O(nm)\)

最后跑最短路即可;总时间复杂度 \(O(nm \log nm)\)

9.16

P10652 [ROI 2017] 前往大都会 (Day 1) (最短路 DAG + 斜率优化 DP)

对第一问,直接建图最短路即可

考虑如何解决第二问

由于有 "最短路" 的大前提,考虑先建出最短路 DAG,这样就可以扔掉这个限制

考虑在最短路 DAG 上 DP;先从简单情况考虑

若最短路 DAG 为一条链,可以直接设 \(f_i\) 表示到点 \(i\) 的答案

显然,一条铁路在链上会被切成很多段,我们应该将每段看成不同的铁路考虑

转移即为 \(f_i \leftarrow f_j + (\text{dis}_i-\text{dis}_j)^2\),要求 \(i, j\) 在最短路 DAG 上属于同一铁路连续段

拆开转移式,为 \(f_i \leftarrow f_j + \text{dis}_i^2 + \text{dis}_j^2 - 2 \text{dis}_i \text{dis}_j\);这显然可以斜率优化,利用 \(2\text{dis}_i\) 单增,可以做到 \(O(n)\)

当最短路 DAG 不为一条链时,我们可以按拓扑序更新,维护每个铁路连续段的凸包

具体的,更新点 \(i\) 时,先把 \(i\) 放在每个凸包中查询得到 \(f_i\),再将 \(i\) 对应的点加入每个凸包即可

时间复杂度 \(O(s \log s + s)\)

以下是斜优复习部分

考虑将转移式变为 \(F_1(j) = F_2(i)F_3(j) + F_4(i)\)\(y = kx+b\) 的形式

\(f_i = f_j + \text{dis}_i^2 + \text{dis}_j^2 - 2 \text{dis}_i \text{dis}_j\) 移项,可得 \(f_j + \text{dis}_j^2 = 2 \text{dis}_i \text{dis}_j + f_i - \text{dis}_i^2\)

\((\text{dis}_j, f_j+\text{dis}_j^2)\) 看作平面直角坐标系内一点,画出经过该点的斜率为 \(2 \text{dis}_i\) 的直线,此时 \(f_i-\text{dis}_i^2\) 即为直线的截距

我们需要最大化 \(f_i\),可视作让斜率为 \(2 \text{dis}_i\) 的直线从上向下平移,第一次碰到点时的截距即为所求

设有三点 \(A, B, C\),其中 \(x_A < x_B < x_C\);考虑什么时候 \(B\) 能被 \(A, C\) 偏序

若斜率 \(K_{AB} \le K_{BC}\),直线斜率为 \(k_0\)

  • \(k_0 \ge K_{AB}\)\(A\) 不劣于 \(B\)
  • \(k_0 \le K_{BC}\)\(C\) 不劣于 \(B\)
  • 综上,\(B\) 有用当且仅当 \(K_{BC} < k_0 < K_{AB}\);但由 \(K_{AB} \le K_{BC}\),这种情况不合法

因此,必然有 \(K_{AB} > K_{BC}\);容易发现只需维护一个上凸包

考虑对于斜率 \(k_0\),如何判断在哪个点取到最大值

设上凸包中的点从左往右依次是 \(Q_1, Q_2, \cdots, Q_{\text{cnt}}\)

从右往左枚举点,设当前枚举到 \(Q_j\);若 \(k_0 \ge K_{Q_jQ_{j-1}}\),说明 \(Q_j\) 没有 \(Q_{j-1}\) 优,继续向下枚举;反之点 \(Q_j\) 必然最优

本题中,由于 \(k_0\) 单增,当前不优的点以后也不优,可以直接弹出;查询总时间复杂度就是 \(O(n)\)

\(k_0\) 没有单调性,可以在凸包上二分,查询总时间复杂度 \(O(n \log n)\)

考虑求出 \(f_i\) 后,如何将 \(i\) 对应的点加入凸包

由转移式,易知 \(i\) 对应的点为 \(P_i(\text{dis}_i, f_i+\text{dis}_i^2)\)

从右往左枚举凸包中的点,设当前枚举到 \(Q_j\);显然,若 \(K_{P_iQ_j} \ge K_{Q_jQ_{j-1}}\),需要弹出 \(Q_j\);反之直接插入 \(P_i\) 即可

总插入时间复杂度 \(O(n)\)

实现上,由于 \(\text{dis}_i\) 单增,每次只会向后加点,可以用单调栈 / vector 维护凸包

9.17

P9734 [JOISC 2021] 逃走経路 (Escape Route) (Day2) (分讨 + 最短路 + 枚举瓶颈边 + 单调栈二分)

考虑将所有路径按跨天 / 不跨天分成两部分

先考虑跨天的路径;设询问为 \((u, v, t)\)

对于这种路径,又可以分成第 \(1\) 天 / 中间若干天 / 最后 \(1\) 天三部分:

  • \(1\) 天,我们从 \(u\) 走到某个城市 \(p\),并留在 \(p\) 待到第二天

    由于有 "断边时间" 的限制,且 \(q, n\) 极不平衡,直接对每个询问从 \(u\) 跑最短路是不可取的

    考虑这条路径的不变量;由于我们要在 \(p\) 待到第二天,从 \(p\) 倒推的时间其实是确定的

    具体的,考虑枚举 \(p\),对每个点求出能走到 \(p\) 的最晚出发时间,记为 \(f_{p, i}\)

    这可以通过从 \(p\) 时间倒流跑最短路解决

    \(n\) 很小,可以求出所有的 \(f_{i, j}\),这部分时间复杂度 \(O(n^3)\)

  • 最后 \(1\) 天,我们从某个城市 \(q\) 走到 \(v\)

    由于已知在 \(0\) 时刻出发,容易直接最短路解决,记为 \(g_{q, i}\)

    求出所有的 \(g_{i, j}\),这部分时间复杂度 \(O(n^3)\)

  • 对中间若干天,容易想到若 \(g_{i, j} \le S-1\) 则连边 \((i, j, 1)\),在新图上跑最短路即可,记为 \(d_{i, j}\)

    求出所有的 \(d_{i, j}\),时间复杂度 \(O(n^3)\)

  • 综上,答案即为 \(\displaystyle S-t + \min_{p, q} [f_{u, p} \ge t](d_{p, q}S+g_{q, v})\)

    注意到限制只与 \(p\) 有关,每次都枚举 \(p, q\) 是不必要的

    考虑枚举 \(p, v\),打包预处理 \(\displaystyle \min_q (d_{p, q}S+g_{q, v})\),记为 \(\text{tot}_{p, v}\)

    则答案为 \(\displaystyle S-t + \min_p [f_{u, p} \ge t](\text{tot}_{p, v})\),时间复杂度 \(O(qn)\),可以接受

再考虑不跨天的路径

对这种路径,难点在于出发时刻不确定,到达时刻也不确定

考虑我们真正关心的只是限制最严 (最早断掉) 的那条边,即瓶颈边

考虑按照瓶颈边对路径分类,枚举瓶颈边 \((x, y, l, c)\),预处理此时 \(u, v\) 间路径的信息

本质上,此时我们已经确定了 "最晚到 \(x\) 的时刻" 以及 "从 \(y\) 出发的时刻" 两个不变量,类似之前的思路:

  • 预处理 \(\text{pre}_i\) 表示从 \(i\) 出发,能在 \(c-l\) 时刻及以前到达 \(x\) 的最晚出发时间

    预处理 \(\text{suf}_i\) 表示从 \(y\)\(c\) 时刻出发,到 \(i\) 的最早时间

  • 综上,瓶颈边为 \((x, y)\) 时,答案即为 \(\text{suf}_v-\text{pre}_u\),要求从 \(u\)\(\text{pre}_u\) 时刻及以前出发

    考虑对所有瓶颈边预处理,时间复杂度 \(O(n^2m)\)

    考虑单调栈维护 \((u, v)\) 间的所有可选路径,按最晚出发时间升序加入,淘汰掉最晚出发时间更早 + 距离更长的路径

    查询时做单调栈上二分即可,时间复杂度 \(O(q \log m)\)

综上,总时间复杂度 \(O(n^3 + n^2m + qn + q \log m)\)

9.18

P4637 [SHOI2011] 扫雷机器人 (缩点 + 有用点概率转所有点概率 - 枚举排列 + bitset 维护可达性)

\(u\) 能引爆 \(v\),则连边 \(u \rightarrow v\),考虑先缩点,记第 \(i\) 个 SCC 的大小为 \(\text{siz}_i\)

"在未引爆地雷中随机引爆" 很烦,因为未引爆地雷会动态变化,我们没法很好的刻画答案

考虑把 CF1773G - Game of Questions 的思路逆过来:

  • 在 CF1773G 中,我们发现相邻两次 "关键问题" (能使场上存活的人变化) 间的 "无效问题" 的概率是不必考虑的

  • 在本题中,考虑把相邻两次 "主动引爆的地雷" 间的 "间接引爆的地雷" 补上

    具体的,每次我们在还未选择的地雷中随机选一个,若其已经被间接引爆则跳过

    此时,引爆序列会形成一个排列

综上,即随机一个排列,其贡献为其中 "主动引爆的地雷" 的个数

考虑拆贡献;点 \(i\) 有贡献当且仅当在所有能主动 / 间接引爆它的点中,它在排列中第 \(1\) 个出现

设点 \(i\) 的大小为 \(\text{siz}_i\),能主动 / 间接引爆它的点的大小之和为 \(\text{cnt}_i\),则点 \(i\) 的贡献就是 \(\displaystyle \frac{\text{siz}_i}{\text{cnt}_i}\)

按拓扑序更新,bitset 维护可达性即可

时间复杂度 \(\displaystyle O(\frac{nm}{w})\)

9.19 - 9.20

复习 CSPS 初赛 + 初赛 + 摆烂

9.21

模拟赛

9.21 T1 - 巅峰对决 (数组配对 / 打表找规律)

部分分:\(O(n^3)\)

逆序对的形式启示我们从大到小填,往已经填的里插

\(f_{i, j, 0/1}\) 表示从大到小填到 \(i\),共填了 \(j\) 个数,逆序对个数为偶 / 奇的方案数

转移大概为 \(f_{i, j, 0/1} \leftarrow f_{i+1, j-k, 0/1} \times w(j-k, k, 0/1)\)

其中,\(w(i, j, 0/1)\) 表示已有 \(i\) 个数,将 \(j\) 个小于已有所有数的值插进去,形成偶 / 奇个新逆序对的方案数

具体的,\(w(i, j, 0/1)\) 为类似组合数卷积的形式,可以 \(O(n^3)\) 预处理

初始值为 \(f_{m+1, 0, 0} = 1\),答案为 \(f_{1, n, 0}\)

DP 转移是 \(O(n^3)\) 的,总时间复杂度 \(O(n^3)\)

正解:

看到逆序对数奇偶,考虑对数列进行两两配对

\(n\) 为偶数:

  • \((a_1, a_2), (a_3, a_4), \cdots\) 的方式对数列内部两两分组

  • 若有 \(a_1 = a_2, a_3 = a_4, \cdots\),容易发现每个逆序对都会贡献偶数次,必满足要求,方案数为 \(m^\frac{n}{2}\)

  • 反之,找到第 \(1\) 个满足 \(a_{2i-1} \ne a_{2i}\ (i \ge 1)\)\(i\),按 \(i\) 对数列进行分类

  • 容易发现,交换 \(a_{2i-1}, a_{2i}\) 后必会使逆序对数奇偶性变化

    此时,令交换 \(a_{2i-1}, a_{2i}\) 形成的数列与原数列配对,必然为双射 (都能两两配上)

    这种情况的方案数为 \(\displaystyle \frac{m^n-m^{\frac{n}{2}}}{2}\)

  • 综上,此时总方案数为 \(\displaystyle \frac{m^n+m^{\frac{n}{2}}}{2}\)

\(n\) 为奇数,只需多考虑 \(a_1 = a_2, a_3 = a_4, \cdots, a_{n-2} = a_{n-1}, a_n\) 的情况

由于 \(a_n\) 在末尾,贡献也必然为偶,成立

综上,此时总方案数为 \(\displaystyle \frac{m^n+m^{\frac{n-1}{2}} \times m}{2}\)

合并两种情况,答案为 \(\displaystyle \frac{m^n+m^{\lceil \frac{n}{2} \rceil}}{2}\)

细节上,对于 \(2\) 没有逆元的情况,可以先对 \(2p\) 取模,最后再把答案除以 \(2\)

主播主播,观察性质太费脑子了,有没有简单又快速的方法?

有的,兄弟有的,打表

你说得对,但是题解确实写了 "出题人希望选手打表找出规律"

反思:

  • 你说得对,但是我表都打出来了还没看出规律,那咋办
  • 有时候就是会在 T1 遇到这种 adhoc,不能全场死磕 T1,应该推推其他题

9.21 T2 - 月 (贪心 - 两两配对 + 连边刻画)

部分分:\(z_i = 0\)

典题,考虑先按 \(x_i\) 排序取走第 \(1\) 个,剩下的按 \((2, 3), (3, 4), \cdots\) 两两配对,每对取 \(y_i\) 更大的

\(x_i\),最劣情况即取 \(x_1, x_3, x_5, \cdots\),但此时有 \(x_1 > x_2, x_3 > x_4, \cdots\),正确性没问题

\(y_i\),每组都取更大的,正确性显然也没问题

正解:

首先,为方便讨论,若 \(n\) 为奇数则补一个 \((0, 0, 0)\) 变成偶数

\(\lceil \frac{n}{2} \rceil+1\) 实际上多给了一次选择,而我们正好多出了一维

考虑对 \(y_i\) 按同样的方式处理,排序后取走第 \(1\) 个,剩下的配对

\(x_i\)\(y_i\) 的所有配对,只需满足每对至少取走一个,\(x_i\)\(y_i\) 的限制就符合要求

这启示我们连边刻画

具体的,将每对的两个点连边;显然每个点只会连两条边,因此形成了许多偶环

\(x_i, y_i\) 的要求转化为对每条边,我们要选择其中至少一个端点

仍然考虑配对思想,每个环有全选奇数号点 / 全选偶数号点两种方式,取 \(\sum z_i\) 更大的即可

显然,这样构造时 \(z_i\) 的限制也一定能满足

反思:

  • 之前做过弱化版,不应该没想出来;还是理解不够深刻
  • 还是不应该死磕 T1;相比 T1,其实这题我更可能想出来

9.21 T4 - 神秘的字符串题 (转化限制 + 括号树上树形 DP)

套路地,考虑建出括号树

关键就在于如何刻画 "向前平移"

考虑设 \(t_i\) 表示第 \(i\) 位的左括号最终在哪里被消掉

事实上,我们只需满足如下条件:

  • \(t_i \le i\),因为只能向前移
  • \(t_i \equiv i\ (\bmod 2)\),因为移动步长为 \(2\)
  • \(t_i \ge t_{\text{fa}_i}\),因为 \(\text{fa}_i\) 相对 \(i\) 更靠前

其余的不合法情况 (如一个括号跨过另一个括号) 都可以调整成代价相等且合法的情况

考虑对 \(t_i\) DP;具体的,令 \(f_{u, i}\) 表示 \(u\)\(i\) 处消掉,\(u\) 子树的最小代价

转移为 \(\displaystyle f_{u, i} \leftarrow c_i + \sum_v \min_{j \ge i} f_{v, j}\ (v \in \text{son}_u)\),且 \(i\)\(u\) 合法

显然可以记录后缀 \(\min\) 优化,时间复杂度 \(O(n^2)\)

反思:刻画能取到的充要条件是个常见 trick,需要记住

9.22

9.21 T3 - 不经典矩阵题 (笛卡尔树 + 大力分讨)

考虑 "经典矩阵题"

枚举答案矩形上边界所在行 \(i\),对第 \(j\) 列,记从第 \(a_{i, j}\) 开始向下的极长 0 连续段长度为 \(h_j\)

容易发现这是最大子矩形问题,建笛卡尔树解决即可

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

考虑原问题

首先解决 01 的情况

\(a_{i, j}\)01,容易发现答案矩形只能全部在其上 / 下 / 左 / 右,即:

  • 上边界最小为 \(i+1\)
  • 下边界最大为 \(i-1\)
  • 左边界最小为 \(j+1\)
  • 右边界最大为 \(j-1\)

对四个方向分别做一次 "经典矩阵题",取前缀 / 后缀 \(\max\) 更新答案即可

这部分时间复杂度 \(O(nm)\)

再解决 10 的情况

考虑在 "经典矩阵题" 做法的基础上,再把 \(1\)1 变成 0 会带来什么变化

仍然枚举答案矩形上边界 \(i\),考虑再枚举更改后的最短极长 0 连续段长度所在位置 \(j \ (1 \le j \le m)\),分讨:

  • 选择更改 \(j\) 所在列的上个 1,容易得到此时新的 \(h_j\)

    向左右两边分别二分,得到 \(h_j\) 管辖的最宽范围即可

    这部分时间复杂度 \(O(nm \log m)\)

  • 选择更改限制 \(j\) 所在列取得最小值的位置 \(k\) 所在列的上个 1 (即拓宽 \(h_j\) 管辖范围)

    此时可以选择向左改 / 向右改,要求此时新的 \(h_k \ge h_j\),两边分别维护一次即可

    \(k\) 的更左侧 / 更右侧 + \(j\) 的右侧 / 左侧二分,求出 \(h_j\) 的新管辖范围

    这部分时间复杂度 \(O(nm \log m)\)

综上,总时间复杂度 \(O(nm \log m)\)

事实上,我们只需要动态维护 \(h_j\) 左 / 右第 \(1\) 个与第 \(2\) 个满足 \(h_k < h_j\) 的位置 \(k\)

注意到随着 \(i \leftarrow i-1\)\(h_j\) 的变化只能是清零或 \(+1\)

根据这一性质,可以考虑链表维护 \(h_j\),查前驱的前驱做到 \(O(nm)\)

9.23

CF1361E - James and the Chase (随机化 + dfs 树分讨 + Tarjan 思想)

考虑如何判断一个点 \(u\) 是否是 "好点"

以点 \(u\) 为根建 dfs 树,则 \(u\) 是好点等价于不存在横叉边与前向边

这启示我们在以 \(u\) 为根的 dfs 树上考虑;接下来考虑如何判断另一点 \(v\) 是否是好点

由于有 "简单路径" 的限制,\(v\) 到其子树中的点必然满足要求

\(v\) 子树外的点:

  • 由于强连通的性质,每个点必然被至少 \(1\) 条返祖边覆盖

    P.S. 此处称返祖边 \((x, y)\) 覆盖点 \(v\),当且仅当 \(x\)\(v\) 子树中且 \(y\)\(v\) 的祖先

  • \(v\) 子树中有 \(\ge 2\) 条返祖边覆盖了 \(v\),则 \(v \rightarrow \text{fa}_v\)\(\ge 2\) 条简单路径,\(v\) 不为好点

  • \(v\) 子树中只有 \(1\) 条返祖边覆盖 \(v\),设为 \((x, y)\)

    • \(y\) 为好点,\(v\) 也为好点,因为从 \(v\)\(v\) 子树外的点必须先经过 \(y\)

    • \(y\) 不为好点,显然覆盖 \(y\) 的返祖边的端点不能在 \(v\) 子树中 (不然 \(v\) 就会被两条返祖边覆盖)

      \(y \rightarrow z\) 有两条简单路径,\(v \rightarrow y \rightarrow z\) 同样会有两条,\(v\) 不为好点

综上,点 \(v\) 为好点,当且仅当满足:

  • \(v\) 被恰好 \(1\) 条返祖边覆盖
  • 覆盖 \(v\) 的返祖边 \((x, y)\) 满足 \(y\) 是好点

对限制 \(1\),可以树形 DP 解决

\(f_u\) 表示 \(u\) 被多少条返祖边覆盖,\(\text{in}_u\) 表示有多少条返祖边指向 \(u\)\(\text{out}_u\) 表示有多少条返祖边从 \(u\) 引出

转移为 \(f_u \leftarrow \text{out}_u - \text{in}_u + \sum f_v\ (v \in \text{son}_u)\)

初始值为对叶子 \(u\),有 \(f_u = \text{out}_u\)

对限制 \(2\),考虑 Tarjan 思想,\(\text{low}\) 数组即为所求

现在回过头考虑如何求出一个好点

注意到 "好点个数 \(\le 0.2n\) 则输出无解" 的限制,考虑随机化

随机 \(50\) 次,每次暴力建树 check 即可

时间复杂度 \(O(n+m)\)\(50\) 倍常数

P3209 - 平面图判定 (刻画限制 + 观察上界 + 2-SAT)

考虑 "保证存在哈密顿回路" 这个性质的作用

考虑将哈密顿回路画在平面上,必然将整个平面分成了两部分;其余的边要么连在环里,要么连在环外

设点 \(u\) 在回路上的编号为 \(\text{id}_u\);则边 \((u_1, v_1), (u_2, v_2)\) 冲突当且仅当 \([\text{id}_{u_1}, \text{id}_{v_1}], [\text{id}_{u_2}, \text{id}_{v_2}]\) 相交且两边均连在环内 / 外

对每条非回路边建两个点表示在环内 / 环外,2-SAT 刻画冲突关系即可

直接做时间复杂度 \(O(m^2)\),需要优化

显然,环内最多连 \(n\) 条边,环外同理;那么总共最多连 \(n+n+n = 3n\) 条边 (还要加上环上边)

因此,\(m > 3n\) 时直接输出无解,反之 2-SAT 即可

时间复杂度 \(O(n^2)\)

以下为 2-SAT 复习部分

设限制为 "\(x_i\) 为真则 \(y_i\) 为假",连边 \((x_i, 1) \rightarrow (y_i, 0)\) 与其逆否命题 \((y_i, 1) \rightarrow (x_i, 0)\),表示 \(u\) 能推出 \(v\)

对每个 SCC,其中一个点成立则其他的点都成立;因此考虑缩 SCC

设点 \(i\) 所在编号为 \(\text{scc}_i\);显然,若存在 \(u\) 使得 \(\text{scc}_{(u, 1)} = \text{scc}_{(u, 0)}\),则矛盾,必然无解

反之,构造时 \(u\)\(\text{scc}_{(u, 0)}\)\(\text{scc}_{(u, 1)}\) 中拓扑序更大的点对应的布尔值即可

实现上,SCC 编号越大代表越晚出栈,越晚出栈则拓扑序越小,直接取 SCC 编号较小的点作为答案即可

时间复杂度 \(O(n)\)

ABC277Ex - Constrained Sums (2-SAT - 对值域拆点刻画赋值)

注意到值域 \(m\) 很小,考虑对值域拆点

具体的,把每个变量拆成 \(2(m+2)\) 个点,分别表示 \([x _i \ge j], \neg [x_i \ge j]\ (j \in [0, m+1])\)

首先考虑每个变量拆出的点间的限制:

  • \(x_i \ge 0\) 必然成立,连边 \(\neg [x_i \ge 0] \rightarrow [x_i \ge 0]\)

  • \(x_i \ge m+1\) 必然不成立,连边 \([x_i \ge m+1] \rightarrow \neg [x_i \ge m+1]\)

  • \(x_i \ge j+1\)\(x_i \ge j\),连边 \([x_i \ge j+1] \rightarrow [x_i \ge j]\)

    同时,对其逆否命题连边 \(\neg [x_i \ge j] \rightarrow \neg [x_i \ge j+1]\)

再考虑题目的限制 \(L_i \le x_{a_i}+x_{b_i} \le R_i\)

  • 显然,\(x_{a_i}, x_{b_i} \le R\),连边 \([x_{a_i} \ge R_i+1] \rightarrow \neg [x_{a_i} \ge R_i+1]\),对 \(x_{b_i}\) 同理

  • 显然,\(x_{a_i}, x_{b_i} \ge L_i-m\),连边 \(\neg [x_{a_i} \ge L_i-m] \rightarrow [x_{a_i} \ge L_i-m]\),对 \(x_{b_i}\) 同理

  • \(x_{a_i} \ge j\)\(x_{b_i} < R_i-j+1\),连边 \([x_{a_i} \ge j] \rightarrow \neg [x_{b_i} \ge R_i-j+1]\)

    对称的,连边 \([x_{b_i} \ge j] \rightarrow \neg [x_{a_i} \ge R_i-j+1]\)

  • \(x_{a_i} < j\)\(x_{b_i} \ge L_i-j+1\),连边 \(\neg [x_{a_i} \ge j] \rightarrow [x_{b_i} \ge L_i-j+1]\)

    对称的,连边 \(\neg [x_{b_i} \ge j] \rightarrow [x_{a_i} \ge L_i-j+1]\)

  • P.S. 以上要求出现的数都 \(\in [0, m+1]\),否则不连该边

跑 2-SAT 并构造方案即可

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

9.24

打罕见的阳间场 CodeForces Round 1053 (Div.2)

咋回事,D 都切不了,还是太不会观察性质了……

CF2151A - Incremental Subarray (观察性质)

CF2151B - Incremental Path (模拟)

CF2151C - Incremental Stay (观察性质 - 向中心移动,隔位前缀和)

9.25

P5332 [JSOI2019] 精准预测 (2-SAT + 观察图性质 + 分组 bitset)

显然,一个火星人若在 \(t+1\) 时刻活,\(t\) 时刻必然活;\(t\) 时刻若死,\(t+1\) 时刻也必然死

注意到这与 \([x_i \ge j]\) 类似,考虑 ABC277Ex - Constrained Sums 的套路,对每个火星人拆点刻画生存状态

\((i, j)\) 表示第 \(i\) 个火星人在 \(j\) 时刻活,\(\neg (i, j)\) 表示死

类似的,连边:

  • \((i, j+1) \rightarrow (i, j)\)
  • \(\neg (i, j) \rightarrow \neg (i, j+1)\)
  • 对限制 \((0, t, x, y)\),连边 \(\neg(x, t) \rightarrow \neg(y, t+1)\),及其逆反条件 \((y, t+1) \rightarrow (x, t)\)
  • 对限制 \((1, t, x, y)\),连边 \((x, t) \rightarrow \neg (y, t)\),及其逆反条件 \((y, t) \rightarrow \neg (x, t)\)

\(O(nT)\) 个点显然无法接受

注意到只有题目输入的时间及 \(T+1\) 有用,只保留这些点,这样点数就是 \(O(n+m)\) 级别的

注意到这个图有非常好的性质:

  • 生点只按 \(t\) 从大向小连边
  • 死点只按 \(t\) 从小向大连边
  • 生死点间只有对应 \(t\) 间连边,且总是从生点连向死点

综上,不难发现整个图是个 DAG,因此无需缩点

考虑如何求 \(\displaystyle \sum_{1 \le i \le n, i \ne k} \text{Live}(k, i)\)

  • \(k\) 必死 (即 \((k, T+1)\) 可达 \(\neg (k, T+1)\) ),答案为 \(0\)

  • 反之,从 \((k, T+1)\) 出发遍历整张图,记到达的 \(\neg (i, T+1)\) 个数为 \(\text{cnt}\),答案为 \(n-\text{cnt}-1\) (还要除去自己)

    特殊地,对必死点 \(p\),其他 \((k, T+1)\) 都必定要到达它对应的 \(\neg (p, T+1)\),这样才能保证正确性

    因此,我们先求出所有必死点 \(p_i\),再建虚点 \(0\),连边 \((k, T+1) \rightarrow 0\)\(0 \rightarrow p_i\)

暴力搜时间复杂度 \(O(n(n+m))\),无法接受

注意到这是 DAG 连通性问题,考虑用 bitset 维护,时间复杂度 \(O(\frac{n(n+m)}{w})\)

但这样空间会炸,这就需要用到分组 bitset 的 trick

考虑将所有 \(\neg (i, T+1)\)\(B\) 个分成一组,对每组分别搜一次,只维护到组内点的可达性,最终将结果累加

一共跑 \(\frac{n}{B}\) 次,每次时间复杂度 \(O(n + \frac{B(n+m)}{w})\),空间复杂度 \(O(\frac{B(n+m)}{w})\)

综上,总时间复杂度 \(O(\frac{n^2}{B} + \frac{n(n+m)}{w})\),空间复杂度 \(O(\frac{B(n+m)}{w})\)

实现上很卡常,取 \(B = 10^4\) 时效率较高

9.26

CF2151D - Grid Counting (观察性质)

限制 \(2\) 等价于:

  • 格子 \((1, 1)\) 需染黑
  • 格子 \((2, 1), (2, 2), (1, 2)\) 需恰选 \(1\) 个染黑
  • 格子 \((3, 1), (3, 2), (3, 3), (2, 3), (1, 3)\) 需恰选 \(1\) 个染黑
  • ……

限制 \(3\) 等价于:

  • 格子 \((1, n)\) 需染黑
  • 格子 \((1, n-1), (2, n-1), (2, n)\) 需恰选 \(1\) 个染黑
  • 格子 \((1, n-2), (2, n-2), (3, n-2), (3, n-1), (3, n)\) 需恰选 \(1\) 个染黑
  • ……

由上,可发现一些格子必定不能填:

  • 由限制 \(2\)\(1\) 条,格子 \((1, 1)\) 需染黑

    由限制 \(3\)\(n\) 条,格子 \((2, 1), (3, 1), \cdots, (n, 1), (n, 2), \cdots, (n, n)\) 必不能填

    对称的,格子 \((2, n), (3, n), \cdots, (n, n), (n, n-1), \cdots, (n, 1)\) 必不能填

  • 由限制 \(2\)\(2\) 条,格子 \((1, 2), (2, 2)\) 需恰选 \(1\) 个染黑

    由限制 \(3\)\(n-1\) 条,格子 \((3, 2), (4, 2), \cdots, (n-1, 2), (n-1, 3), \cdots, (n-1, n-1)\) 必不能填

    对称的,格子 \((3, n-1), (4, n-1), \cdots, (n-1, n-1), (n-1, n-2), \cdots, (n-1, 1)\) 必不能填

  • ……

综上,能填的区域为从左上角到右下角的斜线 + 从右上角到左下角的斜线 + 矩形上端围成的区域 (边框上也能填)

同时,我们要求每列恰好填 \(1\)

显然,考虑从限制严到限制松填,即从下往上填;总方案数只需乘组合数即可

时间复杂度 \(O(n \log \text{mod})\)

9.27

摆烂 + 补 whk

9.28

CF2151E - Limited Edition Shop (刻画限制 + 线段树优化 DP)

考虑按照 \(a_i\) 的顺序考虑,每个物品有被 Alice 选与被 Bob 选两种决策

我们肯定希望从前到后 DP,考虑一段 \(a_i\) 前缀的选择分配方案什么时候是合法的:

  • 若指定当前分配给 Bob,则没有要求

    这是因为,我们并不要求 Bob 已选的物品形成 \(b_i\) 中的前缀,实际顺序上可以视为先选在 \(a_i\) 中靠后的,再选靠前的

  • 若指定当前分配给 Alice,记 Bob 已选的物品在 \(b_i\) 中的最大编号为 \(\text{id}\),当前物品在 \(b_i\) 中的编号为 \(\text{id}'\)

    显然,我们要求 \(\text{id}' > \text{id}\)

    容易发现,保证这一点就能使方案合法

考虑 DP;记 \(f_{i, j}\) 表示分配完 \(a_i\)\(\text{id} = j\) 时的答案

转移为:

  • \(a_i\) 分配给 Alice,此时要求 \(\text{id}' > j\)

    有转移 \(f_{i, j} \leftarrow f_{i-1, j}+v_{a_i}\ [j < \text{id}']\)

  • \(a_i\) 分配给 Bob,且 \(\text{id}'\) 不为新的 \(\text{id}\)

    有转移 \(f_{i, j} \leftarrow f_{i-1, j}\ [\text{id}' < j]\)

  • \(a_i\) 分配给 Bob,且 \(\text{id}'\) 为新的 \(\text{id}\)

    有转移 \(f_{i, \text{id}'} \leftarrow f_{i-1, k}\ [k < \text{id}']\)

直接做时间复杂度 \(O(n^2)\)

这显然是线段树优化的形式,可以做到 \(O(n \log n)\)

9.29

CF1691C - Sum of Substrings (观察性质)

CF1310C - Au Pont Rouge (SA + 二分转判定 + DP check)

由于 \(n \le 1000\),可以将所有子串拿出来排序,求出 \(\text{rk}_{l, r}\)

实现上可以用 SA 维护,时间复杂度 \(O(n^2)\)

考虑二分答案串 \(s\),DP 求出有多少方案满足字典序最小的串 \(\ge s\);最后 check 是否 \(\ge k\) 即可

考虑枚举划分的子串以转移;由于确定 \(l\) 时容易比较字典序,考虑从后向前 DP

\(f_{i, j}\) 表示划分完 \([i, n]\),分成 \(j\) 个子串,字典序最小串 \(\ge s\) 的方案数

转移即为 \(f_{i, j} \leftarrow f_{k, j-1} [\text{rk}_{i, k+1} \ge \text{rk}_s]\);初值为 \(f_{n+1, 0} = 1\),答案为 \(f_{1, m}\)

注意到合法的 \(k\) 必然是一段后缀,可以预处理 + 后缀和优化,时间复杂度 \(O(n^2)\)

总时间复杂度 \(O(n^2 \log n)\)

CF616F - Expensive Strings (SA + 前缀和)

套路的将所有串用特殊字符隔开,建 SA 维护子串出现次数

枚举 \(i\),考虑 \(\text{h}_i\) 所在极长连续段 \([l, r]\) (满足 \(\displaystyle \text{h}_i = \min_{l \le k \le r} \text{h}_k\) ) 对应的所有原串位置:

  • \([l, i]\) 对应原串中 \(\text{lcp}(\text{suf}_j, \text{suf}_i)\ [l-1 \le \text{rk}_j \le i-1]\)
  • \([i+1, r]\) 对应原串中 \(\text{lcp}(\text{suf}_i, \text{suf}_j)\ [i+1 \le \text{rk}_j \le r]\)
  • 当起始位置相同时,对应 \(\text{rk}_j = i\)
  • 综上,需满足 \(l-1 \le \text{rk}_j \le r\)

\(\text{from}_i\) 表示原串位置 \(i\) 所属输入串编号;对于原串位置 \(j\),其贡献为 \(\text{h}_i \cdot \text{c}_{\text{from}_j}\)

综上,\(\text{h}_i\) 所在极长连续段 \([l, r]\) 对应的总贡献为 \(\text{h}_i \sum_{j=l-1}^{r} \text{c}_{\text{from}_{\text{sa}_j}}\)

前缀和维护即可;这部分时间复杂度 \(O(n \log n)\)

有个细节:仅考虑 \(\text{h}_i\) 无法覆盖串只出现 \(1\) 次的情况

容易发现,这种情况下仅有可能是整串

枚举串编号 \(i\),若相邻 \(\text{rk}\) 对应的前后 \(\text{lcp}\)\(\ge |s_i|\),则用 \(|s_i| \cdot c_i\) 更新答案

总时间复杂度 \(O(n \log n)\)

posted @ 2025-10-04 09:20  lzlqwq  阅读(30)  评论(0)    收藏  举报