『板刷 AGC』[AGC016] A~E 做题记录

远古的一场 AGC,能够把前四题做出来,后面两个看了题解还是只会 E,F 是最近才拉过的一道题,但我不会,没办法我还是太菜了。。

A: Shrinking

人机签到题。

先枚举我们最终保留的字符 \(c\),然后我们就按照题意模拟一边,每次从 \(s\) 更新到新的字符串 \(s'\) 的时候,我们希望得到的 \(s'\) 中有尽可能多的 \(c\) 字符,因此如果 \(s_{i},s_{i+1}\) 中存在 \(c\),就令 \(s'_i\leftarrow c\);否则就随机选,因为这一步无论怎么选都不会影响到后面的字符串。

记录 \(c\) 这个字符的答案,比完 \(26\) 个字符的答案就行了。

时间复杂度 \(O(|s|^2)\)

B: Colorful Hats

人机分析题。

分析一下性质,设 \(col_i\) 表示 \(i\) 帽子的颜色,我们任取两个不同的帽子 \(i,j\),设剩下的 \(n-2\) 个帽子的颜色集合为 \(S\)。我们考虑根据 \(i,j\) 的颜色与 \(S\) 之间的关系进行讨论:

  • \(col_i,col_j\) 都不属于 \(S\),那么根据题意显然有 \(a_i=a_j=|S|+1\)
  • \(col_i,col_j\) 中恰好有一个属于 \(S\),不妨设 \(col_i\in S,col_j\notin S\),则有 \(a_i=|S|+1,a_j=|S|\)
  • \(col_i,col_j\) 都属于 \(S\),那么就有 \(a_i=a_j=|S|\)

因此 \(a\) 中元素的极差应该在 \([0,1]\) 中。

接着,我们就对这个极差进行分讨:

  • 若极差为 \(0\)。则每个帽子的颜色最多只有两种构造方案,一种是每个帽子颜色独一无二,一种是满足每种颜色在所有帽子中至少出现 \(2\) 次。因此帽子中出现的颜色个数有两种取值范围,一种是 \([n,n]\),一种是 \([1,\lfloor\frac{n}{2} \rfloor]\)。由此,我们可以推出 \(a_1\) 的取值,显然有 \(a_1\in [1,\lfloor\frac{n}{2} \rfloor]\cup[n-1,n-1]\),后面不取 \([n,n]\) 是因为要排除 \(i\) 本身的颜色。

  • 若极差为 \(1\),设 \(p,q\) 分别为 \(a\) 中的最小值和最大值,\(s_1,s_2\) 分别为 \(a_i=p\)\(a_i=q\)\(i\) 的个数。根据一开始我们分析:\(a_i-a_j=1\Rightarrow col_i\in S,col_j\notin S\)。枚举所有的 \(a_i=q\)\(i\)\(a_j=p\)\(j\) 代入这个条件,则我们能够确定 \(a_i\) 较小的 \(s_1\) 个帽子的颜色\(n\) 个帽子中独一无二,进而得到颜色总数固定为 \(p+1\)。而对于一个 \(a_i=q\)\(i\),必然存在另一个帽子与其颜色相同。因此我们只需要判断颜色总数的范围,即 \(p+1> s_1\)\(p+1-s_1\in [1,\frac{s_2}{2}]\cup [s_2,s_2]\)。其中 \(p+1-s_1\) 表示 \(a_i\) 较大的帽子颜色种类数量。

因此我们对于上面两种情况,判断 \(a_1\) 或者 \(p\) 的取值就行了。

C: +/- Rectangle

人机构造题。

要使得每个 \(h\times w\) 的子矩阵内元素和为负数,且整个矩阵内元素和为正数,则我们肯定是让每个 \(h\times w\) 的子矩阵元素和尽可能大,最好取到 \(-1\)

我们可以这样构造,对于所有满足 \(i\bmod h=1\)\(j\bmod w=1\) 的坐标 \((i,j)\),我们在 \((i,j)\to (i+h-1,j+w-1)\) 这个矩阵中全部放入相同的 \(v\),然后把 \((i+h-1,j+w-1)\) 这个位置的元素改为 \(-(h\times w-1)\times v-1\)。这样每个 \(h\times w\) 的子矩阵内的元素和都为 \(-1\)

\(x=H\bmod h,y=W\bmod w\),若 \(x=0,y=0\),则显然无论怎么构造都是无解的。对于其它的所有情况,我们把 \((1,1)\to (H-x,W-y)\) 这一部分的子矩阵拎出来,它内部的元素和为 \((-1)\times \frac{H-x}{h}\times \frac{W-y}{w}\),而除了这个子矩阵外,我们剩下的元素就一定是正数,因为我们的构造方案中是把负数放在了 \((i+h-1,j+w-1)\),除非是 \(x=0,y=0\),不然你在剩余部分是不可能取到这个负数的。

最后我们就来考虑 \(v\) 该怎么取值,在最劣情况下,\((1,1)\to (H-x,W-y)\) 之外的元素个数会取到 \(\min(H,W)\),因此我们只需要满足:

\[v\times \min(H,W)+(-1)\times \frac{H-x}{h}\times \frac{W-y}{w}\geq 0 \]

\[-(h\times w-1)\times v-1\geq -10^9 \]

用一个程序检验一下可以知道 \(v=1000\) 是万能解,按照 \(v=1000\) 进行构造就行了。

D: XOR Replace

人机结论题。

假定 \(a\) 始终保持为初始的序列,\(s\) 表示当前序列。设初始 \(a\) 的异或和为 \(x_0\),将要修改的位置为 \(i\),我们发现一次操作后 \(s_i\) 变成了 \(x_0\),而当前异或和就先去掉 \(a_i\),再重新异或一个 \(x_0\),即 \(x_0\bigoplus a_i\bigoplus x_0=a_i\),设第二次操作是在 \(j\) 上,则有 \(s_j\leftarrow a_i\),当前异或和变成 \(a_i\bigoplus s_j\bigoplus a_i=s_j\),以此类推。

综上,我们发现操作的本质就是在 \(a\) 的末尾加上一个 \(x_0\),然后弄一个操作序列 \(S=\{t_1,t_2,t_3,\dots,t_m\}\),表示第 \(i\) 次操作为交换 \(a_{t_i},a_{t_{i+1}}\) 的值。最后就是让 \(a\) 的前 \(n\) 项与 \(b\) 相同。

于是判无解的方式就很明显了,就是看 \(b\) 元素的可重集是否是 \(a\) 元素的可重集的子集。

当然,如果有 \(a_i=b_i\),那我们就忽略掉这个 \(i\) 就行了,这个一定不会影响我们的答案。

先考虑一个粗略的二分图建图思路,上部为 \(a\) 的点,下部为 \(b\) 的点,对于 \(a_i=b_j\) 连一条有向边,从上部的 \(i\) 连向下部的 \(j\),边权为 \(1\),由于每次要用上一次被操作的位置去替换别人,因此我们还要对每个 \(i\) 从下部的 \(i\) 连向上部的 \(i\),边权为 \(0\)。我们的目的就是求最短的一条从 \(x_0\) 所在点开始的路径使得下部的所有点都被经过。

但是这样肯定是难以实现的。我们发现对于一个 \(i\) 可能会有多个 \(j\) 满足 \(a_i=b_j\)。不过我们可以思考这些连边的本质,其实就是权值替换。题目要求的是让权值对应,而我们的暴力连边还额外承受了具体的下标这一元素,我们大可不必考虑到底是哪些下标的数在交换。因此我们更改连边策略,在值域上进行连边,每次从 \(b_i\) 连向 \(a_i\),表示有一个位置要用初始序列中的一个 \(b_i\) 去替换掉它的 \(a_i\),则一条路径就表示若干个数之间交换的传递性,因此我们只需要从 \(x_0\) 开始走,找一条经过所有边的路径。

不过仔细想想就会发现我们连出来的图可能不是一个连通块,这很好解决,我们只需要等 \(x_0\) 所在连通块处理之后,直接花费 \(1\) 的代价移动到另一个连通块就行了,其本质就是处理了 \(x_0\) 连通块的答案之后,我们用多出来的数去处理另一个连通块,由于这个数在连通块中不存在连边,它就不会对答案造成多余影响。

由于每条边都会被经过一次,且除开无解情况后每个连通块必然存在一条欧拉回路,我们只需要关心有多少个连通块。直接用并查集维护一下好了。

最后的答案就是连边数量加连通块数量减一。

E: Poor Turkeys

人机暴力题。

挺妙的,我根本想不到,我是人机。

首先可以思考到底怎么操作才能使得一只火鸡 \(i\) 留下来。我们把每个人选择的两个火鸡 \(x,y\) 进行连边,如果存在一个 \(j\) 使得 \(i,j\) 之间有连边,那么我们肯定就要杀掉 \(j\),但是这样的前提是 \(j\) 能撑到这条边连接的时刻,因此我们要考虑如何操作才能使得 \(j\) 在这条边连接之前存活下来。这样,问题就形成了一种递归形式。

具体地,我们要让 \(i\) 最终存活,则对于每一条连接了 \(i\) 的边 \((i,x)\),我们必须要保护好 \(x\),不然等到 \((i,x)\) 这条边时,因为 \(x\) 已经被吃了,那 \(i\) 就必然被吃。于是目的就变成了保护这些 \(x\),以此我们得到所有的用来保护 \(i\) 活到最后的火鸡,设其集合为 \(S_i\)

因此我们考虑时光倒流,从后往前枚举时间 \(t\),对每个火鸡 \(i\) 维护集合 \(S_i\),表示为了使 \(i\) 存活,只考虑 \(t\) 这个时间之后的边我们需要保护的火鸡集合,初始有 \(S_i=\{i\}\)。对于当前时间 \(t\),设这个时刻的连边为 \((x,y)\),我们思考如何修改每一个 \(S_i\)

如果对于一个 \(i\),有 \(x\in S_i\wedge y\in S_i\),则两者之间必然要选择一个被吃掉,即两者必然有一个不能被保护,那么 \(i\) 就一定不能活到最后。如果 \(x,y\) 中恰好有一个属于 \(S_i\),不妨设其为 \(x\),由于我们需要保证 \(x\) 一直活到 \(t\) 之后的某条连边,那么此时此刻就只能去吃掉 \(y\),因此在 \([1,t-1]\)\(y\) 必须活着,不然此刻 \(x\) 必然会被吃掉,于是我们把 \(y\) 放进 \(S_i\) 里面。

最后我们就要判断 \(i,j\) 是否可以同时活到最后,如果 \(i,j\) 有一个被确定活不到最后那就肯定不行。对于其它情况,我们只需要枚举另一只火鸡 \(k\),如果有 \(k\in S_i\wedge k\in S_j\),则两者不能同时存活。用归纳法来证明一下:

证明:

\(f(k)\) 表示若 \(k\in S_i\wedge k\in S_j\)\(i,j\) 能够同时存活。

各自找到两条边 \((k,x),(k,y)\) 使得 \(x\in S_i\wedge y\in S_j\),且在上述枚举过程中 \(k\)\(x,y\) 更晚放入对应的集合。

  • \(x\not=y\),不妨设 \((k,x)\)\((k,y)\) 之前被连接,则此时 \(k\) 会为了 \(x\) 而提前牺牲,从而不能保护后来的 \(y\),那么 \(S_i,S_j\) 中必然有一个元素不能被保护,因此有 \(f(k)=0\)

  • \(x=y\),则 \(f(k)=f(x)\)。由于最终必然会递归到一个点 \(p\) 使其连接了 \(i\)\(j\),因为 \(i\not= j\),此时根据第一个部分必然有 \(f(p)=0\),从而所有递归下去的 \(f(k)=0\)

根据这个结论直接暴力枚举就行了,时间复杂度 \(O(nm+n^3)\)

posted @ 2024-10-09 22:08  Supor__Shoop  阅读(7)  评论(0编辑  收藏  举报
Document