集训队论文浅读 - 信息学竞赛中构造题的常用解题方法

抽屉原理

\(n\) 个物品放入 \(k\) 个抽屉中,其中至少有一个抽屉中有 \(\lceil \dfrac{n}{k} \rceil\) 个物品,并一定有一个抽屉包含 \(\lfloor \dfrac{n}{k} \rfloor\) 个物品。

构造题中考虑构造不同情况的抽屉,应对构造权值类问题。对于取整符号要敏感。

Codeforces 1450 C2

构造出 \((r + c) \equiv i \mod 3\) 的三个抽屉(\(0 \leq i \lt 3\)),分情况讨论,更改抽屉内字符,XOOX

Submission

Gym 102900 B

注意到把地雷改成空地,空地改成地雷并不会改变空地上的数字和。

所以考虑构造 2 中方案:

  • A 变成 B
  • A 改成和 B 相反

两种操作中只会在恰好一种方案中被修改,一共有 \(n \times m\) 种方案,保证最优选择操作数较小的一种,操作数不会超过 \(\lfloor \dfrac{nm}{2} \rfloor\) 次,满足抽屉要求。

DFS 树

对于 DFS 树上边的定义可以移步 OI Wiki

这里需要记住,在构造题中更常用的是无向图上的 DFS 树:将每条边按照第一次经过时的方向进行定向,则无向图的 DFS 树满足所有非树边都是 back edge。

Codeforces 1364 D

\(l = \lceil \dfrac{k}{2} \rceil\)

对图建 DFS 树后,考虑每条非树边 \((u, v)\),如果 \(|dep_u - dep_v| \lt k\),就直接取出 \((u, v)\) 加上 \(u \to v\) 的树上直径构造出一个长度不超过 \(k\) 的简单环。

否则再考虑两种情况:

  • 如果 \(m = n - 1\),此时图本身为一棵树。将点按奇偶性分成两个集合后取较大的的集合,它是大小至少应为 \(\lceil \dfrac{n}{2} \rceil \geq l\) 的独立集,任选 \(l\) 个即可满足要求
  • 如果 \(m \gt n - 1\),那么 DFS 树上存在不满足 \(|dep_u - dep_v| \lt k\) 的非树边,也就是说搜索树的深度至少为 \(k\),并且任意一对深度在 \([2, k)\) 的点中都没有边相连。取出深度最大的点 \(x\),跳 \(x\)\(2, 4, \dots, 2 \times l - 2\) 级祖先才可以取出独立集。

Submission

LOJ #3176

显然可以设 \(a \leq b \leq c\),容易发现只要其中有两个集合联通我们就可以通过导节点来使得集合仍然联通并且大小变成 b。

对于无解情况的判定确实比较困难,所以自然引出先考虑图为树的情况。

当图为一棵树时,集合 \(A\)\(B\) 都是其中的子树,因此一定存在一条边使得 \(A\)\(B\) 分居边的两侧。所以只要找到一条边能让两侧较小和较大的子树大小分别不小于 \(a, b\) 即可。注意到两侧较大的子树一定包含树的重心,所以考虑从重心做文章。

如果将重心删去后最大的连通块大小小于 \(a\),则无解。否则设这个连通块的大小为 \(x\),由重心的性质可以得到 \(x \leq \dfrac{n}{2}\),所以删除这棵子树后还剩 \(n - x \geq \dfrac{n}{2}\) 个点。又由于 \(b \leq \dfrac{n}{2}(b \leq c)\),因此这棵子树与重心之间的边就是我们要找的边。

回到常规分析,建立图的 DFS 生成树。找到 DFS 树的重心,记为 \(u\),再记 \(u\) 上方子树为 \(T\)\(u\) 下方的子树为 \(S_1, S_2, \dots, S_k\)。考虑分类讨论:

  • 如果 \(T\) 或者某一个 \(S_i\) 的大小不小于 \(a\),采用和树一样的方法构建一组合法解。
  • 但如果 \(T\) 和所有的 \(S_i\) 的大小都小于 \(a\),就要回归到无向图上 DFS 树的性质。因为不同的 \(S_i\) 之间并没有边直接相连,但是有一些 \(S_i\)\(T\) 相连。如果所有的与 \(T\) 相连的 \(S_i\) 加上 \(T\) 的大小之和小于 \(a\),则必定无解,因为这表示集合 \(A, B\) 都需要包含重心 \(u\)。从 \(T\) 开始,依次加入与 \(T\) 相连的 \(S_i\),直到其大小不小于 \(a\)。设得到的点集为 \(X\),则 \(X\) 是联通的,可以在其中选出 \(A\)。同时由于 \(T\) 和所有 \(S_i\) 的大小之和都小于 \(a\)\(X\) 的大小不超过 \(2a\)。而且 \(2a + b \leq a + b + c = n\),因此删除 \(X\) 之后,剩余的点数至少为 \(n - 2a \geq b\),我们可以在其中选出集合 \(B\)

Submission

递归法

在一些构造题中,对于不同的输入,问题的结构都比较相似,也就意味着我们的构造有很大的相似性或者周期性。这时,我们往往可以通过递归的方式,对子问题进行构造。

当然,递归更可能作为一种思想:在实现上会有代码难写和时空复杂度高的缺点,需要留心。

例题可以看 jly 的论文具体分析,思路比较难想,但是代码实现起来很简单。

GDKOI 讲座构造题选练

LG-P8902

容易发现约束条件 \(r_{i, i + 1}\) 十分关键,帮助我们获取关于 \(a_i\)\(a_{i + 1}\) 之间的差值。

据此,先确定 \(a_1\),比如设为 \(0\)。然后根据差值进行验证,通过前缀和找出最大最小值,复杂度为 \(O(n^2)\)

posted @ 2024-01-24 09:02  起汐Yuics  阅读(42)  评论(0编辑  收藏  举报