CF 1019 Div.2 解题报告
CF 1019 Div.2 解题报告
A
首先,对于任意若干个数 \(\{a_n\}\),一定可以构造出 \(\{b_n\}\),使得 \(\forall_{i \in [1,n]} a_i*b_i=a_1*b_1\)。
那么题意转化为 \(a\) 中本质不同元素个数。
B
题意:给定一个只由 \(01\) 构成的且长为 \(n\) 的字符串 \(t\),\(s='0'+t\)。
现在你可以翻转(指左右翻转)\(s\) 的一个子串,请最小化 \(s\) 中满足 \(s_i \neq s_{i+1}(i \in [2,n+1])\) 的下标 \(i\) 的个数。
简单思考后分类讨论:
-
若这样的下标个数为 \(2\),那么我们肯定可以通过翻转使下标个数减一;
-
若这样的小标个数大于等于 \(3\),那么我们肯定可以通过翻转使下标数减二;
C
题意:给定一个数组 \(a\),定义 \(med(l,r)\) 表示 \(a_l,a_{l+1},\cdots,a_r\) 的中位数(定义为第 \(\lceil \frac{r-l+1}{2} \rceil\) 小的数)。
问是否存在 \(l,r(1 \le l < r <n)\) 满足 \(med(med(1,l),med(l+1,r),med(r+1,n)) \le k\)。
一个经典 Trick:判断中位数是否为一个数,那么就将大于它的数设为 \(1\),小于等于它的数为 \(-1\),求和后若和为正,那么中位数小于等于这个数。
转化后题意为:能否将 \(a\) 划分为三个非空子串,使得至少两个子串内的元素和小于等于 \(0\)。
分别暴力从前往后、从后往前枚举维护当前子串和,如果当前子串和小于等于 \(0\),那么就新开一段。
有解的情况可以是:
-
从前往后可以划分出至少两段;
-
从后往前可以划分出至少两段;
-
两端可以划分出两段,且两段的并不为全集。
D
题意:给定一个长 \(n\) 的排列 \(a\)。对这个排列进行操作,直到排列中只剩一个数:
-
若这是第奇数次操作,那么删去所有不满足小于左右两边的数的元素;
-
若这是第偶数次操作,那么删去所有不满足大于左右两边的数的元素。
现在给出每一个元素被删去的时间,请还原这个排列。
首先,我们凭直觉想到分析被删去的数是什么。(这是有一定道理的,因为显然没被删去的数限制更强,这是不利于我们构造的)
然后,我们先考虑偶数次操作:
删除的数满足其大于左右两边中至少一个数,这可以是 'V' 字型,也可以是楼梯型。但是出于懒惰,我们选择楼梯型。
那怎么保证楼梯型一定可以呢?
考虑一个最无脑的办法:让删去的数大于所有留下的数,这样就一定保证删去的数不是局部最大值/最小值。
从实现上,我们选择用剩余的数的一段前缀或后缀来填充被删去的数。
E
题意:给定一个长 \(n\) 的数列 \(a\) 和一个整数 \(k\),你可以至多进行以下操作 \(3n\) 次:
-
选择一对 \(i,j\) 满足 \(a_i+a_j=k\)。
-
选择一个数 \(x\),满足 \(x \in [0,k]\)。
-
\(a_i \leftarrow x,a_j \leftarrow k-x\)。
问你能否在限制次数内使得数列不降。
分析:
看到“序列不降”,想到给序列排序。
排序就要想能不能实现 \(swap\) 函数。
我们想一想怎么样可以交换两个数 \(i,j\):
-
\(a_i+a_j=k\):显然;
-
\(a_i+a_x=k\):先操作 \(i,k\) 并将 \(a_i\) 赋值为 \(a_j\),然后再操作 \(k,j\) 将 \(a_j\) 赋值为原来的 \(a_i\)。
其它就不太好想了。
我们看第二种情况,有一个启发:我们不一定要直接交换两个数,我们可以通过一些“中转点”来实现交换。
- 若存在 \(i,j\) 满足 \(a_i+a_j=k\),我们可以交换任意 \(x,y\) :具体地,先交换 \(i,x\),再交换 \(j,y\),此时 \(a_x+a_y=k\),直接交换即可。
那么我们按值从小到大,将值交换到最后一个有序的数的下一个位置。
可以证明这样总是可以的。
F
看不懂,鸽了。

浙公网安备 33010602011771号