『板刷 AGC』[AGC017] A~E 做题记录
这场打得更菜了,只会 A,B,D,没办法,人机是这样的,我还是太菜了。
A: Biscuits
人机计数题。
一个直接的思路是把 \(a\) 的所有数对 \(2\) 取模,然后选出 \(m\) 个 \(a_i=1\) 的 \(i\) 满足 \(m\bmod 2=p\),而剩下的 \(a_i=0\) 的 \(i\) 就是可选可不选。设 \(s=\sum_{i=1}^n[a_i\bmod 2=1]\),则我们的答案为:
B: Moderate Differences
人机智障题。
题目限制了相邻两项差分的值的绝对值在 \([C,D]\) 之中,于是我们可以根据差分数组来求出原数组,不难发现对于一个合法的差分数组 \(b\),我们无论怎样重排 \(b\),最后得到的原数组 \(a\) 也必然合法(这里的差分数组不考虑首项)。那么我们就可以把差分值为正的放到前面,把差分值为负的放到最后,这样我们得到的 \(a\) 就是一个上凸函数。
因此我们考虑构造这样一个序列 \(a\),满足 \(a_1=A,a_n=B\),且存在一个 \(k\) 满足 \(a\) 在 \([1,k]\) 这一段递增,在 \((k,n]\) 这一段递减。我们枚举这个 \(k\),求出 \(a_k\) 的取值范围为 \([A+(k-1)C,A+(k-1)D]\cup [B+(n-k)C,B+(n-k)D]\),本题只需要判断有无解,我们就直接判断这两个区间是否有交即可。
C: Snuke and Spells
人机思维题。
我们思考一下在合法的数组中删除每个数的过程,设 \(num(x)\) 表示 \(\sum_{i=1}^n[a_i=x]\),\(r\) 表示当前剩余的数的个数,那么接下来操作后剩余的数就是 \(r-num(r)\),即 \(r\leftarrow r-num(r)\)。记 \(f(r)=r-num(r)\),那么我们剩余的数的变化就是 \(n\to f(n)\to f(f(n))\to \dots\)。
观察这个形式,我们会发现它和倍增很像,因为倍增就是用来处理这种函数迭代 \(k\) 次的问题的。那我们就用一个类似的问题替换本题的外表。实际上就是在数轴上从 \(n\) 开始跳,设当前点为 \(x\),每次都会跳到 \(f(x)\) 这个点上,直到最后我们跳到了 \(0\) 这个原点。我们把每一次跳跃的过程想象为一条线段,即对于每个点 \(x\) 画一条覆盖 \([f(x),x]\) 的线段,那么对于一个合法的数组,我们的所有线段必然会覆盖 \([0,n]\) 这一段区间。对应的,我们的不合法数组就必然不能使得所有线段覆盖 \([0,n]\)。
由此,我们来考虑如何用最少的改变次数使得数组合法。假如我们把一个数 \(a_i\) 改为了 \(v\),那么 \(a_i\) 对应的 \([f(a_i),a_i]\) 线段就会缩成 \([f(a_i)+1,a_i]\),\(v\) 对应的 \([f(v),v]\) 线段就会增长为 \([f(v)-1,v]\)。也就是说每次修改最多会使得被覆盖的长度增加 \(1\)。因此我们的最少修改次数就是未被线段覆盖的长度。
Q:为什么不用考虑另一条线段缩短对长度带来的 \(-1\) 的影响呢?
A:因为根据定义有 \(\sum x-f(x)=n\),如果我们的线段不能覆盖完 \([0,n]\),就说明我们有许多的线段覆盖到了重复的区域,因此我们从贪心的角度来说,每次都缩短这些重复的线段,那么每次修改的代价就必然为 \(+1\)。
因此我们用差分维护一下每个点被覆盖的次数,然后对于题目给的修改,我们就分别缩短和增长对应的线段,动态维护答案即可。
D: Game on Tree
人机博弈题。
我们把当前的树的状态视作一个节点,对一次操作前后的两种状态连一条有向边,那么问题就变成了有向图博弈,考虑 \(\text{SG}\) 函数。
设 \(\text{SG}(x)\) 表示以 \(x\) 为根的子树 \(\text{Sub}(x)\) 的 SG 值。若 \(x\) 为叶子节点,显然有 \(\text{SG}(x)=0\),否则就要通过 \(\text{Sub}(x)\) 删除一棵内部的子树来进行转移。如果 \(x\) 存在多个儿子的话,设 \(f_{x,y}\) 表示 \(\text{Sub}(x)\) 中只保留 \(\text{Sub}(y)\) 这个儿子子树的 SG 值,则有 \(\text{SG}(x)=\bigoplus_{y\in \text{Son}(x)} f_{x,y}\),我们只需要知道 \(f_{x,y}\) 怎么求。
考虑一个性质,对于一条链,我们的 \(\text{SG}(i)=\text{mex}\{\text{SG}(1),\text{SG}(2),\dots,\text{SG}(i-1)\}=\text{SG}(i-1)+1\),因为 \(\text{SG}(1)=0\),所以这个我们就可以用归纳法证明。
运用这个性质,我们考虑在一条链上不断加点,使得链变成奇形怪状的树,我们在不断加点的过程中不断使用数学归纳法,就会发现每次加了一个点之后,这棵树的 SG 值就会变为原来的 SG 值加一。
于是我们就能得到 \(f_{x,y}=\text{SG}(y)+1\)。
因此我们的转移方程就是:
E: Jigsaw
人机图论题。
不难得到一个思路,就是对于两个拼图 \(i,j\),如果 \(i,j\) 能够左右相接,就在 \(i,j\) 之间连边,最后就是判断所有点能否连接成若干条链。
但是暴力建边是 \(O(n^2)\) 的,我们考虑根据 \(H\) 这个变量优化一下,因为它的范围很小。对于一个拼图 \(i\),我们定义两个值 \(l_i,r_i\),有:
则对于两个拼图 \(i,j\),如果 \(r_i+l_j=0\),则 \(j\) 可以接在 \(i\) 的右边。我们朝图论的方向进一步转换,可以发现等号的转换可以构成一张图,因此我们可以让 \(l_i\leftarrow -l_i\),然后条件就变成了 \(r_i=l_j\)。考虑对每个拼图 \(i\) 建立一条 \(l_i\rightarrow r_i\) 的有向边,此时拼图就相当于一条边,值域上的每一个数就变成了点。
因此,对于一个拼图序列 \(A\),如果我们可以顺次把 \(A\) 中的所有拼图拼在一起,则我们就一定可以在图上找到一条包含这些拼图对应的边的有向路径。于是问题就变成了能否在 DAG 上找到经过所有边的路径,且保证起点为一个负权,终点为一个正权。
根据半欧拉图判定,设 \(\text{deg}_i=\text{in}_i-\text{out}_i\),我们知道一个 DAG 存在一条欧拉路径当且仅当至多一个顶点的 \(\text{deg}\) 等于 \(-1\),至多一个顶点的 \(\text{deg}\) 等于 \(1\),其余点的 \(\text{deg}\) 等于 \(0\)。不难想到 \(\text{deg}\) 等于 \(-1\) 的必然是起点,等于 \(1\) 的必然是终点,而我们本题还要使得起点为负权,终点为正权,因此我们还要加上这两个条件。
此外,我们知道一个 DAG 中若所有点的 \(\text{deg}\) 都等于 \(0\),那么整张图就是欧拉图而不是半欧拉图,因此我们选出的欧拉路径全部都是欧拉回路,这显然是不合法的。因此我们还需要判掉这个情况。
按照上面的条件依次判断就行了。时间复杂度 \(O(n+H)\),我也不知道为什么 \(H\) 开得比较小。