疫苗的
昏昏倒地
Debuff 下,云完了前四题就去美化了
# CF1534
# A
题意:
的字符矩阵,只含字符 R
W
.
,要把所有 .
的地方换成 R
W
,要求 R
上下左右不是 R
, W
同样的要求。
题解:
发现一个点即可把所有的地方染好色
很小,暴力染色即可。
注意初始没有一个色的时候。
这种 sb 题要注意认真检查每一步的细节,不要翻车。
# B
题意:
给定 列的直方图,每列有个高度 ,一个图的丑陋度为裸露在外的竖线长度和,如:
每次可把一个地方高度减一,最小化 操作数+丑陋度
和。
题解:
简单考虑贡献法贪心
容易发现若一列高于旁边两列,削它每次 操作数+1
丑陋度-2
,这样是优的,而削到与两边较大的那列相同高度时贡献会减小。
注意特判边界情况
# C
题意:
给出 ,每行是个排列,可以交换一列两个元素,要求经过操作后没有相同元素在同一行的数阵有多少个。
题解:
对于每一个列连入一个并查集中,最后答案为 , 为联通块数量。
由于相同的数字不能在同一行,这又是两个排列,这样一来,我们一个联通块中,一列翻了之后其余都要做相应的转换,于是就有翻不翻两种情况。
# D
题意:
交互题,一棵树,可进行不超过 次询问,每次询问一个 ,返回 个数,表示每个点到 的距离,还原树的结构。
题解:
先随便问个点 ,得到的距离中, 的就是与他相邻的,我们把距离为奇数点或偶数点中选出较小的那个集合,问一遍就做完了。
可以发现奇数点或偶数点集合中较小的那个一定是小于 的。
# P
题解:
交互题,长度为 的序列与 ,每次可询问 个数字 ,返回 。求
题解:
我们并不关心每个 具体是多少,于是可以看做翻牌子,每次可翻 个牌子,求最终每个牌子被翻奇数次的方案。
设每个地方被翻 次,我们要求:
此时操作了 次,于是 ,然后构造出 ,先赋每个 为 ,每次加 。为什么这样有解?不会证明,当然得首先特判掉 为奇数且 为偶数的情况,接下来就对了?????
# F1
题意:
一个 的方格,有些地方有沙子,干扰一块沙子能使从这块沙子到最底下的路径中,擦到的沙子都掉下来,求最少干扰的沙子数。
题解:
把一个点向所有他能干扰得到的,最上边的沙子连边,跑缩点,找入度为 的点即可。
# F2
题意:
上题的基础上,每列有个 ,要求每列至少掉 个沙子的最小干扰数。
题解:
把每列从下到上第 个沙子称作关键点,则只要这一块掉下来就可以了。
先把关键点能到的其他关键点删掉,它不配,只要删掉之前关键点,这一块自然会掉。
可以发现缩点后每个点干扰后能影响的关键点是一段连续的区间,简单证明下,假设 列中第 列的点能够影响到 列中关键点,却不能影响 列中的关键点,那 一连串影响到 的链中在 列一定有个点,在 列关键下面,那 也可以走这条链影响到 ,于是这样的第 列关键点就在之前被 列关键点吃掉了,它不配作为关键点。
所以可以通过反拓扑的方法求出每个点能够影响到的关键点左右端点,此时相当于要求一个最小线段数覆盖整个区间,简单贪心即可:把线段按左端点从小到大为第一关键字,右端点从大到小为第二关键字,排序。每次处理到 表示把 区间全部覆盖完消耗的最小线段数,用个左端点在 以内的,能推到的最远 更新即可。
参考代码
1 | sort(seg, seg + scnt, [](const pii &a, const pii &b) { return a.fi == b.fi ? a.se > b.se : a.fi < b.fi; }); |
# G
题意:
平面直角坐标系上有 个点要被处理,在 点处理点 的代价是 ,从 出发,每次可向上 向左走一步,求处理掉所有点的最小代价。
题解:
首先这个切比雪夫距离的代价并不好处理,所以使用一个经典我刚会的套路,把坐标 转换成 ,此时切比雪夫距离就变成了曼哈顿距离,还带有一个 的常数,这个最后把求出的 除以 即可。
这个操作相当于是把坐标系顺时针旋转了 ,所以向右向上的移动变成了 这样斜着走,不难发现一个关键点 在 时处理是最优的,于是把关键点按转换后的坐标排序后可以得出一个 ,设 表示处理到 的最小代价,有转移:
这个 下面的限制意思是从 可以走到 。
定义 为值域大小,这个 的复杂度是 ,于是我们要采用一种神奇的操作把复杂度变成 ,这个操作被叫做 slope trick
,可以上 学习。
对于此题来说,我们把 看做一个函数 ,把 也看成一个函数 , 方程就可以写成 的形式,对于每个转移来说, 是固定的,所以可以看成一个常数,相当于是将一个区间 函数与一个绝对值函数合并得到一个新的函数 。
观察这些函数的性质,发现 是一个凸函数,只有一个转折点 ,而 ,都是由一连串的 合并而来的,是一个分段函数,有一些转折点,且也是一个凸函数(斜率递增),这题要求我们做两种操作:1. 在 中找到最小值。 2. 合并两个凸函数。
最小值显然会在斜率等于 处取得,但这个位置不一定满足在 中,于是我们用一个大根堆 来维护这个分段函数斜率小于 的那一段的每个转折点,每个转折点表示我们的函数在这个转折点处斜率加 ,所以若斜率在一个转折点 处 则在优先队列中放 个转折点 ,类似的,用一个小根堆 来维护分段函数斜率大于 的每个转折点。
利用一点初中数学知识,每次若 则最小值在 处取得,若 则最小值在 处取得,若在 ,则直接取最小值。
还要求合并一个函数 ,相当于是与一个转折点集合 取并,像上面一样讨论一下新转折点该放在哪边,还有一些旧的转折点因为增添了新转折点斜率发生了更改,所以分类讨论把 的最大值移动到 或 的最小值移动到 。
还有一道与这题类似的 slope trick
优化 的题 ,可以去做一做。