省选构造专题做题记录

省选构造专题做题记录

A CF804E The same permutation

\(\text{Link}\)

首先考虑判断无解。有一个经典结论是对于一个排列,每交换任意一对数字后逆序对个数的奇偶性会改变。那么为了让初始状态和结束状态的逆序对奇偶性相同,\(\dfrac{n(n-1)}2\) 必然是 \(2\) 的倍数,那么 \(n\equiv 0,1\pmod 4\)

然后考虑构造,采用归纳法构造。由于 \(n=4\) 是最小的有合法方案的 \(n\),所以我们每次删去 \(4\) 个数字。具体的,先打表打出 \(n=4\) 内部的解,然后还需要把这个组内部的数字和外部之间的交换情况统计上。我们依然将外部的数字每 \(4\) 个分成一组,然后我们需要将两个组之间的所有交换情况进行排列,这个依然可以直接打表求出。

然后所有包含这四个数字的交换情况都已经排列结束了,我们就可以将这四个数字删去,继续求出剩下部分的解即可。这样我们可以完成 \(n\equiv 0\pmod 4\) 的部分。

然后对于 \(n\equiv 1\pmod 4\),我们最后会剩下一个数字没有考虑到。那么实际上我们不需要求出最开始这个组内部的解,我们把这个数字带上,求出一个 \(n=5\) 的组的内部的解,这样就可以排列完所有情况了,然后继续求出剩下部分的解即可。

B AGC046E Permutation Cover

\(\text{Link}\)

首先先看无解的条件。如果不考虑字典序的话我们有一个非常简单的构造方案:每一次加入一个 \(1\sim k\) 的排列 \(p\) 以及 \(p\) 的一个前缀。那么很显然这样的过程最多 \(\min(a)\) 轮,而一个数最大的出现次数正好是 \(2\min(a)\)。所以 \(2\min(a)\ge \max(a)\) 时问题一定有解。

然后考虑 \(2\min(a)<\max(a)\) 的时候问题有没有解。不妨设 \(a_x=\min(a),a_y=\max(a)\),那么对于一个 \(x\),它最多和周围的两个 \(y\) 构成排列,但是由于 \(2\min(a)<\max(a)\),所以必定存在一个 \(y\) 没有配对,于是一定无解。

所以我们得到了无解的充要条件:当 \(2\min(a)<\max(a)\) 时问题无解。现在考虑构造字典序最小的方案。

考虑增量构造,我们每次往当前序列后面加入一个长度 \(l\le k\) 的序列,使得最后 \(k\) 个元素还是一个排列,选出所有序列中字典序最小的那一个即可。那么考虑如何对于一个确定的 \(l\) 构造出最优方案。

首先在确定 \(l\) 之后我们要选的数字就确定了,相对应的,去掉这些数字时候的序列 \(a\) 也就确定了。将这些数字记作集合 \(S\),变化后的 \(a\) 记作 \(a'\),此时我们分类讨论有:

  • \(2\min(a')\ge \max(a')\),那么此时后面必然有解,将 \(S\) 排序后就是合法序列。
  • \(2\min(a')+1<\max(a')\),根据上面的理论,后面的所有 \(x\) 最多匹配 \(2\min(a')\)\(y\),而当前放的最后一个 \(x\) 最多只能再多匹配一个 \(y\)。那么最多匹配上 \(2\min(a')+1\)\(y\),所以此时必然无解。
  • \(2\min(a')+1=\max(a')\),那么此时我们要尽可能将所有 \(a_x=\min(a')\)\(x\) 往后放。更具体的,所有的 \(x\) 都应该在 \(a_y=\max(a')\)\(y\) 的后面。用贪心简单实现即可。

综上我们可以在 \(O(k^2\sum a_i)\) 的复杂度内解决这个问题,可以通过。

C CF1053E Euler tour

\(\text{Link}\)

首先考虑到是欧拉序,所以如果出现一对 \(a_l=a_r\) 的点,那么说明区间 \([l,r]\) 应该代表了一个子树,于是我们就可以递归处理 \((l,r)\),然后将 \([l,r]\) 整体缩成一个点 \(a_l\)。所以不难看出本题的基本思路就是递归求解。

我们考虑如何求解一个区间 \([l,r]\)。先按照上面的做法将所有相邻的相同的数全部缩成一个点,这样一来区间 \([l,r]\) 内就没有相同的数字了。然后我们还知道,对于一段合法的欧拉序,这个区间里面需要恰好有 \(\dfrac{r-l}2+1\) 种不同的权值;如果此时权值数量不足这个数,就填入当前还没有出现过的数字直到补足这个数。

接下来从左往右考虑每个长度为 \(3\) 的区间,如果这个区间中只有最左边或者最右边的数是空缺的(即形如 xy00yx 的形式),我们直接补成 xyx 的样子,然后缩成一个点 x。注意这里修改完之后还要向前跳,看能不能继续修改前面的区间,复杂度显然正确。最后我们这个区间还有可能有一些数没有填进去,我们考虑上一层递归下来的根,把根填到这些空里面即可。

需要额外注意的一点是对于欧拉序而言,整体的开头和结尾必须是一样的,但是我们在递归的时候并没有保证这一点,所以先让 \(a_1=a_{2n-1}\) 然后递归处理 \((1,2n-1)\) 即可。同时在递归处理的时候,需要判断在该区间内出现的所有数字没有在这个区间外出现过,否则也是无解的。

用链表即可实现,复杂度 \(O(n)\),可以通过。

D AGC006E Rotate 3x3

\(\text{Link}\)

首先先考虑倒过来做,即把给出的矩阵还原成原先的样子。

有一些很离谱的错误可以直接判掉。接下来容易发现我们交换不能改变编号的奇偶性,所以原本在奇数列上的现在也得在奇数列上,偶数列同理,这可以再判掉一些无解情况。

接下来我们钦定,每一列如果按照原顺序排列记为正数,否则记作负数。那么一次操作实际上就是先取反再交换。然后我们尝试归约法构造,即尝试找到一个更加普适的操作代替原操作。

  • 引理 1:\(\forall i\in [2,n-3]\),可以同时取反 \(a_i,a_{i+2}\)

考虑如下操作方案:

 1  2  3  4  5
-3 -2 -1  4  5
-3 -2 -5 -4  1
 5  2  3 -4  1
 5  2 -1  4 -3
 1 -2 -5  4 -3
 1 -2  3 -4  5
  • 引理 2:\(\forall i\in[1,n-3]\),可以同时取反 \(a_i\sim a_{i+3}\)

考虑如下操作方案:

 1  2  3  4
-3 -2 -1  4
-3 -4  1  2
-1  4  3  2
-1 -2 -3 -4
  • 引理 3:\(\forall i\in[1,n-2]\),可以同时取反 \(a_i,a_{i+2}\)

实际上这是由上面两个引理共同得出的结论。引理 \(1\) 已经证明了 \(i\) 在中间的可行性,对于 \(i\) 在序列两头的情况,我们可以先利用引理 \(2\) 对两头取反,然后将不需要取反的部分利用引理 \(1\) 变回去即可。

根据上面的引理可以得出一个重要结论:

  • 对于编号奇偶性相同的两列,可以将两列同时取反。

有了这个结论之后,我们实际上只需要将列的编号排列正确,然后保证此时奇数列和偶数列上需要取反的列的数量为偶数即可。接下来考虑将列编号排列正确后这个值的奇偶性如何变化。

先考虑排列奇数列上的数字,容易发现,当我们交换相邻的两个奇数列的数字时,奇数列上需要取反的列数量奇偶性不改变,而偶数列上需要取反的列数量奇偶性会发生改变。也就是说我们需要保证,排列奇数列上的数字所用的次数的奇偶性与原先偶数列上需要取反的列数量的奇偶性一致。

我们知道,将一个排列还原至原排列所需的步数是逆序对个数。所以实际上我们的判断条件就是:奇数列的逆序对个数奇偶性等于偶数列上负数的个数奇偶性。同理,我们也需要满足偶数列的逆序对个数奇偶性等于奇数列上负数的个数奇偶性。

直接求逆序对然后判断是 \(O(n\log n)\) 的,不过有一个经典结论是逆序对个数奇偶性等于排列长度减去置换环个数,所以可以做到 \(O(n)\)

E CF715D Create a Maze

\(\text{Link}\)

首先我们需要考虑一个基本结构:

1 1
1 2

这也就是说,我们可以通过这个结构将当前的方案数 \(\times 2\)。这启发我们进行二进制分解。

不过要利用二进制进行构造,我们除了要完成 \(\times 2\) 这个操作以外,还需要完成 \(\times 2+1\) 这个操作。实际上这个并不难实现,我们给上面的基本结构中开一个口,把外面的一个 \(1\) 引进来即可,即:

x x x
x 1 1
1 2 3

这样的话我们除了维护中间的主体部分以外,还需要额外维护外面的一圈 \(1\) 来辅助分解,那么我们最终的构造应该形如下图:

1 - - x x 
1 - - - x
1 1 - - -
x 1 1 - -

- 的地方就是我们构造的主体部分,1 就是辅助部分。这样的话我们最多能够造出的数字大概是 \(2^{50}\),很遗憾的是这个值没有达到 \(10^{18}\),所以我们需要改进做法。

实际上把基本结构当成 \(2\times 2\) 是有点浪费的,我们将它扩大到 \(3\times 3\)

1 1 1
1 2 3
1 3 6

这样的话我们可以做到单次 \(\times 6\),所以我们可以进行六进制拆分。此时我们需要实现在 \(\times6\) 的基础上加 \(1\sim 5\),依然考虑从基本结构中开口解决。我们有两种本质不同的开口方式,分别可以使答案 \(+3\)\(+1\),拼一起即可完成这个要求。

不过此时我们不能只维护一边的 \(1\) 了,我们要在左边和上边都维护一圈 \(1\) 来辅助,也就是说我们的构造应该形如下:

1 1 1 1 1 x x x
1 - - - 1 x x x
1 - - - 1 1 1 x
1 - - - - - 1 x
1 1 1 - - - 1 1
x x 1 - - - - -
x x 1 1 1 - - -
x x x x 1 - - -

此时我们可以构造出的最大数字大概为 \(6^{24}>10^{18}\),已经可以满足要求了。然后我们现在需要满足障碍物的限制。对于主体部分和辅助部分之间的墙,每个部分最多需要 \(8\) 个障碍物;对于辅助部分和无用部分之间的墙,看似我们也需要 \(8\) 个障碍物,但是实际上在每个转折处,我们只需要保留水平方向或竖直方向上的两个障碍物即可,所以这一部分只需要 \(4\) 个障碍物。加上开头我们封住起点的两个障碍物,总数是 \((8+4)\times 24+2=290\) 个障碍物,可以满足要求。

F CF1276E Four Stones

G CF341E Candies Game

\(\text{Link}\)

平凡情况直接判掉。先考虑较小的情况,即 \(n=3\)。如果我们可以解决 \(n=3\) 的问题,那么我们每次从原序列中抽出三个非零数字做一遍即可减少一个非零数,如此下去必然有解。

考虑三个数 \(x\le y\le z\),我们现在希望把其中一个数变为 \(0\)。先考虑简单的情况,即 \(x=1\),如果我们不断对这个数进行操作,那么我们最后可以得出 \(2^k\)。这启发我们对 \(y\) 进行二进制分解,然后用这个不断消去 \(y\) 的二进制中的每一位,如此即可将 \(y\) 消成 \(0\)

那么容易想到如下流程:

  • 设当前 \(x=2^k\)。如果 \(y\) 的二进制上这一位为 \(1\),操作 \((x,y)\),即可消去 \(y\) 的这一位。
  • 否则的话,操作 \((x,z)\),用 \(z\) 换取 \(x\) 的倍增。

然后考虑 \(x>1\) 的情况,这个也很容易,我们令 \(a=1,b=\lfloor\tfrac{y}{x}\rfloor,c=\lfloor\tfrac{z}{x}\rfloor\)。对这三个数完成上述操作,这样的话我们实际上是使 \(y'=y\bmod x\),很显然这个值小于 \(x\),那么我们递归下去就一定可以完成操作。

然后考虑复杂度,即操作轮数。我们每次会把 \(y\) 变成 \(y\bmod x\),所以这个复杂度和 \(\gcd\) 的复杂度其实是类似的,加上倍增的复杂度,总复杂度 \(O(n\log^2 V)\),可以通过。

H CF1227G Not Same

\(\text{Link}\)

终于做出来一道构造题了。

首先考虑将所有数从大到小排序,然后依次放入。考虑归纳法构造,即我们每次删去一个元素,然后转化为一个对应的子问题求解。

先考虑每次删去的元素,我的做法选择的是删去最大值。我们维护一个 \(x\),表示当前还有 \(x\) 行重复,那么我们就剩下 \(n+1-x\) 行已经满足条件了。当我们加入 \(a_i\) 的时候,我们希望第 \(x\) 行和上面的 \(1\sim x-1\) 行不同,那么我们将 \(a_i\)\(x-1\) 行开始往上填,不填 \(x\) 这一行即可;如果不够的话可以往 \(x+1\sim n+1\) 中填,不会影响答案。

这样的话我们每填一个数 \(x\) 会减一,\(x\) 初值为 \(n+1\),最后 \(x=1\) 表示没有重复,于是我们的构造是合法的。一个小问题在于 \(a_i\) 可能填不满 \(1\sim x-1\),这样的话第 \(x\) 行还是和上面重复的。不过此时 \(x\) 行已经不可能再填数了,而上面的行必须还要填数,否则不满足 \(a_i\le n\) 的要求,这样的话依然是满足要求的。

I CF538G Berserk Robot

\(\text{Link}\)

发现我们给出的限制可以拆成一个区间加上若干倍整个序列和的形式,但是此时我们的 \(x,y\) 两维需要一起考虑,不是非常容易。考虑将坐标系旋转 \(45^\circ\),那么操作就会变为 \((1,1),(1,-1),(-1,1),(-1,-1)\),也就是将 \(x,y\) 两维分开来考虑,这样问题可以变的简单一些。

先考虑一维。我们将限制可以写为若干个三元组 \((a_i,b_i,c_i)\),表示 \(a_i\times sum_l+sum_{b_i}=c_i\),其中 \(sum_i\) 表示 \(i\) 的前缀和。考虑如果我们已知 \(sum_l\),我们就可以轻松求出 \(sum_{b_i}\) 的值,然后我们需要构造一种合法方案。

将三元组按 \(b_i\) 排序,这样解出来的 \(sum_{b_i}\) 就是按照顺序的,我们发现,在相邻的两个 \(b_i\) 之间,我们的构造方式只有两种:

  • \(1,1,1,1\cdots,1,-1,1,-1,\cdots,1,-1\)
  • \(-1,-1,-1,-1\cdots,1,-1,1,-1,\cdots,1,-1\)

由此我们可以得到两个关系,对于 \(sum_p\)\(sum_q\) 而言,我们有一个数量关系和一个奇偶关系:

  • \(|sum_p-sum_q|\le q - p\),即 \(p-q\le sum_p-sum_q\le q-p\)
  • \(|sum_p-sum_q|\)\(q-p\) 奇偶性相同。

如果我们知道 \(sum_l\) 的值,就可以算出所有的 \(sum_{b_i}\),然后判断后进行构造即可。先来考虑 \(sum_l\) 已知的情况,实际上有两种:

  • 存在两个三元组的 \(b_i\) 相等,\(a_i,c_i\) 不等,相减后即可得出 \(sum_l\)
  • 存在一个三元组的 \(b_i=l\)

而剩下的情况我们是不知道 \(sum_l\) 的值的,这里就需要运用上面的两个关系。将 \(sum_{b_i}\)\(sum_l\) 表示,根据上面的两个关系求出 \(sum_l\) 的范围以及奇偶性要求,最后枚举出一个合适的值作为 \(sum_l\) 然后构造即可。

时间复杂度是 \(O(n\log n+l)\) 的,可以通过。需要注意的是上下取整的一些细节,以及为了保证 \(b_n\)\(l\) 这个区间合法,我们在无法求出 \(sum_l\) 的情况中还需要加入一个三元组 \((-1,l,0)\) 来修正。

posted @ 2025-07-19 20:44  UKE_Automation  阅读(45)  评论(0)    收藏  举报