CF2089F1. Serval and Colorful Array (Easy Version)
Serval and Colorful Array (Easy Version)
题意
Serval 有一个魔法数字 \(k\)(\(k \geq 2\))。我们称一个数组 \(r\) 是 colorful 当且仅当:
- 数组 \(r\) 的长度恰好为 \(k\),且
- \(1\) 到 \(k\) 之间的每个整数在 \(r\) 中恰好出现一次
给定一个由 \(n\) 个整数组成的数组 \(a\),其中每个元素都在 \(1\) 到 \(k\) 之间。题目保证 \(1\) 到 \(k\) 中的每个数字在 \(a\) 中至少出现一次。你可以对数组 \(a\) 进行如下操作:
- 选择下标 \(i\)(\(1 \leq i < n\)),然后交换 \(a_i\) 和 \(a_{i+1}\) 的值
要求计算出使得数组 \(a\) 中至少存在一个 colorful 子数组*所需的最少操作次数。可以证明在题目约束条件下,这总是可以实现的。
*注:子数组是指数组中连续的元素序列
在这个版本中, \(2 \le k \le n \le 3000, 1 \le a_i \le k\).
思路
根据数据范围, 可以想到最终复杂度会是一个 \(\mathcal{O}(n^2)\) 或者 \(\mathcal{O}(n^2 \log n)\) 级别的.
假设我们选择了框住的数作为最终子序列的数, 考虑如何计算最小的代价, 也就是最小交换次数.
根据初中数学知识可以知道, 当我们选择中间的数作为不动点的时候, 代价一定是最小的. 与此同时, 我们可以注意到使标记元素连续所需的最小交换次数是「交换前每个标记元素到中间位置的距离之和」与「交换后该距离之和」的差值, 其中「交换后该距离之和」显然是一个定值, 我们可以放到最后来处理.
这样, 我们就可以很自然的想到从 \(1 \sim n\) 对不动点进行枚举.
因为不动点同时又是中间点, 因此我们需要在其左边选择 \(\frac{k}{2}\) 个数, 在右边选择 \(\frac{k}{2}\) 个数. \((\)向上和向下取整无关紧要\()\)
对于每一个 \(1 \le i \le k\), 我们需要确定其是应当从左侧还是右侧进行选择. 不妨设当前枚举的不动点为 \(p\), \(l_i, r_i\) 分别表示 \(i\) 这个数在左或右侧到 \(p\) 的最短距离. 为了满足上面的条件, 一个聪明的贪心想法是我们钦定对于每一个 \(i\) 全部选择左侧, 记和为 \(s\), 同时记 \(\Delta_i = r_i - l_i\), 对 \(\Delta\) 数组进行排序, 然后我们从中从小到大选择 \(\frac{k}{2}\) 个加入到 \(s\) 里面即可. 这样, 对于不动点 \(p\) 一定是最优的.
总时间复杂度 \(\mathcal{O}(n^2 \log n)\), 可以过 \(n \le 3000\).
代码并不难实现, 细节也不多, 就不放了.

浙公网安备 33010602011771号