构造专项

大概可以训练思维。

[ARC103F] Distance Sums#

给出树上每个点到剩下所有点的距离和,求构造出树。

不难想到,如果有相邻的 u,v,那么 DuDv=SizvSizu=2Sizvn。那么就有:Du=Dv+2Sizvn,其中 Siz 表示的是那个节点向外的子树大小。

关于树的构造,一般采取从叶子往上或者从根往下,所以需要找出叶子或根的特征。

这里不难发现,D 最大的只能是叶子,否则它的儿子一定比它大。所以我们每次可以找出一个叶子,然后用上述式子找出它的父亲,连边后把当前点去掉,再找最大的,依次做下去,直到做完或者找不到。正确性是如果当前点是还没去掉的点中的非叶子,一样把它移到叶子 D 会更大,违反了 D 是当前最大的条件。

我们的构造是根据两个相邻的点的差值来构造的,所以我们的结果一定满足两两的差值,但是却不一定满足,所以需要随便挑一个点来检验一下。

P3514 [POI2011]LIZ-Lollipop#

给一个只有 12 的序列,每次询问有没有一个子串的和为 x

看起来并不是一道构造题,反而像 DS 题。但是其实这题是要求构造一组解。所以我们先通过前缀和,可以二分出一个位置,使得它的前缀和大于等于 x。由于只含 1,2,所以这个结果应该是 x 或者 x+1。如果是 x,那么直接输出就可以了。接下来考虑如果是 x+1 怎么办。分类讨论:如果左端点是 1,那么直接让左端点向前一格就行了;否则分讨右端点:如果右端点是 1,那么让左右同时向右一格就行了;否则让左右端点同时加一,并重复上述过程。

不难发现,我们维护每一个 2 的连续段的右端点,然后每次看是否能移动到左右端点中某一个是 1,如果在当前不合法的情况下,无法移动到左右端点某一个是 1,或者在左端点是 2 的情况下,右端点在位置 n,就无解。这样单次询问就做到 O(logn)

P5441 【XR-2】伤痕#

给定一张 n 个点的完全图,求在只保留 n 条边的情况下,将剩余所有边定向,使得选择 4 个点形成强连通分量的方案数最大化。

这题值得单独开一篇。这题蕴含了一个深刻的道理:所有的构造题都可以通过大力手玩得到解法。这题也不例外。大概就是想到,4 个点很容易形成强连通分量,所以考虑最小化不形成强连通分量的方案数。通过枚举所有方案,可以得到 4 个点不构成强连通分量有如下几种类型:

  1. 三条无向边,并且无向边成环,并且环上的点都是出边;
  2. 两条无向边,若无向边有公共点,那么有无向边相邻的所有点都要连一条出边到剩下那个点;若无向边没有公共点,那么一条无向边的两个端点要各连一条出边到另一条无向边的两个端点;
  3. 一条无向边……

发现这么分类太烦了,但是我们在模这些东西的过程中逐渐发现,要使得不构成强连通分量,可以根据被孤立的点的个数分:

  1. 被孤立一个,也就是剩下 3 个点都是向它的出边或都是向它的入边;
  2. 被孤立两个,也就是剩下 2 个点都是向它们的出边;
  3. 情况 1,2 可能同时出现。

如果我们把情况 3 归为第一种,那么总共是 3 种情况,依次讨论。

首先考虑减少一个点指向三个点的情况。对于每个点 i,令它的出度为 di,那么此时当前点构成的第一种情况的方案数为 (di3)。而不难发现,di=n(n3)2。所以我们现在相当于是把一个数拆分成 n 个然后使得 n 个数的函数值 f(x)=(x3)=x(x1)(x2)6 之和最小。对 f 求导得到:f(x)=3x26x+26,其对称轴为 x=2,也就是说,f[2,+] 上递增,即 f[2,+] 上是下凸的。对于下凸函数,不难发现上面那个东西当取得所有的 di 都相等时最小,即 fmin=n×f(n32)=n(n3)(n5)(n7)48

接下来考虑构造一组方案满足上面的约束,并且使得不出现后两种情况。不难(不难吗?真的不难吗?)得到一种构造方式,就是先构造一个正 n 边形,然后每个点向对边的两个点连无向边。然后每个点向后顺次连 n32 条有向出边。不难发现,这样不会有点全是入边,也不会有两两孤立的关系。(差不多长一个漩涡的样子)

此时,最终答案就是 (n4)n(n3)(n5)(n7)48=n(n3)(n2+6n31)48

[AGC029C] Lexicographic constraints#

给出一些字符串的长度,求构造一个字符集的大小使得这些字符串可以按字典序递增。

正常多了。首先考虑如果长度是递增的,那么字符集大小为 1 即可,因为我可以直接在后面加最小的字符。直观考虑,如果下一个长度小于当前的,那么最优构造应该是保留下一位长度的前缀并在最后一个字符使它 +1

不难发现,字符集越大,越能满足递增的条件,所以二分答案,然后用上面的可行性来检验即可。检验的时候,我们可以把字符串当成 k 进制,然后遇到 +1 的时候,判断一下进位就可以了。维护的时候用一个栈维护当前所有的非 0 位即可。

[AGC027F] Grafting#

给定两棵树 A,B,每次对 A 操作可以使得它一个叶子连向任意其它的点,求使得两树相同的最小操作次数。

为了做这个题,我们需要知道如何方便地判断两树相同。很显然,在确定了相同根之后,每个点的父节点如果对应相同,两树就相同。更进一步,我们的操作实际上就是想把所有点的父亲整成相同的。并且我们发现此时如果一个点不操作,它父亲必然无法被操作,也就是说,在确定了根之后,所有点都有一定的操作顺序。

所以我们枚举根,这个根最好是不操作的。然后我们就枚举所有点,判断是否满足:

  1. 如果 u 的父亲都相同,那么 u 所有的祖先都也已经满足与 B 相同。这一点只要建树然后直接判断就可以了。
  2. 如果 u 的父亲不同,那么 u 需要被操作,必须在 faA 之前操作,也同时必须在 faB 之后操作。这一点只需要建立一张图然后跑拓扑就可以了。

但是,这个根不一定是不需要操作的,也就是说,有可能最优情况是所有点都需要操作的。但是一个点不可能被操作多次,所以我们可以直接枚举根第一步移动到那个点去,然后再继续跑上述过程。

这样复杂度是单次 O(n3) 的,n50 这样的数据为什么不暴力一点呢。

[AGC030C] Coloring Torus#

给定一个 k,求构造任意一个方阵,满足其中出现了且只出现了 [1,k] 中的整数,且对于任意两个有相同数字的位置,要满足与它广义相邻 4 个数中,每个数的数量都相同。

考虑到这题的相邻定义,所以没有什么特殊的位置。考虑构造通解。不难发现一个通解是像样例一一样的一个数一行。此时你发现对于一个 k,需要一个 k×k 的矩阵才行。k1000,但我们构造的矩阵最大是 500×500。于是考虑能不能让它的效率乘二。不难对于 k 是偶数的时候得到一个构造:选取一个 n=k2 的矩阵,然后每行两个数交错填。

但是在横着填的时候,你会发现每个位置与它不同色的相关性只有一格,这使得我们无法处理奇数,因为总有一行相同的,而那一行会因为只有一个相邻格与上一行相关。

这太抽象了,但是如果我说斜过来构造,那肯定就差不多了。比如说当 k=8 的时候,构造如下:

1 4 5 8
3 6 7 2
5 8 1 4
7 2 3 6

此时如果我要构造 k=7,直接把 8 换成 7

1 4 5 7
3 6 7 2
5 7 1 4
7 2 3 6

你发现是可以的并且能让矩阵效率乘二。

但是你发现,这个构造在矩阵边长是奇数的时候是不可行的。所以找到一个偶数的边长再构造。

构造题注意对小数据的特判!!!

[AGC035C] Skolem XOR Tree#

给定一个 n,求构造一棵 2n 个节点的树,在 ii+n 节点权值均为 i 的情况下,满足 i[1,n]ii+n 路径上的点权异或和为 i

惊为天人的构造。直接考虑 xxxor1,这两个数串起来然后加个 1 就能满足了。唯一的问题就是如果 n 是个偶数怎么办。我们先把此前的安排好,然后加入 n。此时需要两个数 y,z,满足 nxoryxorzxor1=0。直接取 y=nlowbit(n),z=lowbit(n)+1,此时只要 n 不是二的整次幂就不会有问题。

所以无解就是 n 是二的整次幂。

[AGC041E] Balancing Network#

给定 n 根导线,导线之间有 m 个平衡器。从左到右给出这 m 个平衡器连接的两根导线编号。现不知道它们的方向。一个信号传递的规则是从某导线出发,沿当前导线遇到第一个指向别的导线的平衡器,然后变道到指向的导线。现要求构造这 m 个平衡器的方向,满足:所有导线出发的信号都汇聚到同一根导线(T=1)所有导线出发的信号都汇聚到同一根导线(T=2)。

首先考虑 T=1 的构造。只会暴力,就是枚举最终的汇聚点,然后从后往前枚举所有平衡器,维护能到达当前枚举的汇聚点的集合。如果一个平衡器两端中有一端 x 能到汇聚点,那么另一端 y 也能到。这样暴力做是 O(nm) 的。然后考虑,如果我令 dpi,j 表示当前从 i 开始能到 j,那么每一个平衡器相当于把 dpxdpy 每一个按位或起来,这个可以 bitset 优化。最后找到某一列都是 1,然后再暴力跑一遍求方案就可以了。

然后考虑 T=2。和上面差不多,就只要做的时候维护一下到某条导线结束的不同导线的数量。然后到一个平衡器,就比较两边的数量。首先如果当前这两条导线已经是汇聚到同一根导线了,那么当前这个可以随便连,否则判断当前这两根导线的终点所含有的不同导线数量,多的那边指向少的。然后实时维护即可。不难发现,当且仅当 n=2 时会无解。

ThREE#

给定一棵树,构造排列 p,使得对于树上距离为 3 的点对 (i,j),都有:pipjpi+pj 中至少一个是 3 的倍数。

首先要意识到,树上这样的点对应该是 n2 级别的,意味着不能暴力枚举每个点对。于是考虑贪心构造。首先把 1n 按模 3 的余数分类,所有本质不同的只有 0,1,2。然后 0 与任何数都能配对,而 1 必须和 2 配对。

现在考虑一条 1,2 交替的链,发现这上面任何两个距离为 3 的点对都满足条件。现在将上面任意一个换成 0 仍然会保持合法。所以如果我们的构造能够使得 1,2 合法,这样可以任意替换达到满足 0,1,2 的数量。

扩展上面的链,不难发现构造出来一个黑白染色的图。现在 1,2 数量不一定合法,所以我们需要加入 0,考虑如果 1,2 数量都超过了它们本身的数量,那么就用 0 替换多出的部分一定合法;如果某一个数量少于它本身的数量,那么让全部变成 0(你会发现 0 的数量最多比 1,2 少一个),然后剩下的随便,必然也合法。

所以必然有解。

Odd Sum Rectangles#

要求构造一个 (2n1)×(2m1)01 矩阵,最大化和为奇数的子矩阵个数。

大力猜结论题,证明很烦。写法很简单,主要是要知道,在看到 2n1 这种数据的时候怎么办。先考虑题目中的信息具有极强的对称性,然后这个东西是引导人去想到分治。

比如此题,就是通过分治为 2n11 大小的方阵,然后考虑中间的一行一列的填法。不打算写。

Divide Points#

给你 n 个点和它们的坐标,现在给它们两两连上边,如果在同一组为黄色,不同组为蓝色。现在让你给出任意一种分组方案,使得所有长度相同的边颜色相同。

好神奇。看到这种题一般会想到奇偶性。就是如果我把横纵坐标之和为偶数的分成一组,和为奇数的分成一组,那么显然组内的边长平方都是偶数,组间的边长平方都是奇数。现在要考虑的一点就是如何才能解决所有的坐标都是和为偶数的情况(如果都是奇数不妨看作全部向下平移一格),此时我们希望它能出现一些奇数,于是考虑对它进行缩放。显然不能直接除 2,所以考虑我们所希望的是边长的平方除以 2,所以坐标应该除以 2。所以人类智慧得到坐标变换:(x+y2,xy2),不难发现是顺时针旋转 90o 后缩小 2

由于题目保证有解,所以这样子下去一定会有解。

DIY Garland#

有根树的 i 节点权值为 2i,边权为儿子子树中点权和。现按照边权从大到小给出每条边所连接的父亲点,求构造出原树。

显然,最大边权一定连接着根。

然后考虑我们知道所有的叶子。然后倒序枚举所有边,对每个点维护当前子树中的点权和(或者就是最大编号)然后每次将一条边连到最大编号最小的点上去。还有就是某一个点出现的次数就是其儿子的个数,那一个点我们可以等它儿子都齐了再入堆,否则它不可能连向别的点。可以用堆来维护。

完结撒发#

EricQian:感觉做这种题很有潜在价值

又被 D 了。

应该可以预防一些诈骗。我习惯把构造题分成最优解构造和可行解构造。前者一般比较困难,但是我们可以打暴力找规律;后者可以从通解或者特解入手,多手玩一些小数据。

考虑直径构造;从叶子开始构造;或者从根开始构造;找到在给出信息中会有一定特征的点;找到可以省去一些条件后的构造,然后调整。

网格 考虑边长特点;考虑相邻二者间的最优关系;符合题目的通解关系。

序列 考虑构造顺序;考虑特解后调整;考虑特殊位置。

其它 考虑人类智慧;考虑奇偶性构造;

就当我啥也没说。

posted @   ZCETHAN  阅读(53)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
历史上的今天:
2021-11-09 XJOI 2021.11.9 嗯哦癌批冲剌赛
点击右上角即可分享
微信分享提示
主题色彩