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)\) 级别的.

\[\fbox{5}, 1, \fbox{3}, 1, \fbox{1}, 2, \fbox{2}, \fbox{4}, 1, 3 \]

假设我们选择了框住的数作为最终子序列的数, 考虑如何计算最小的代价, 也就是最小交换次数.

根据初中数学知识可以知道, 当我们选择中间的数作为不动点的时候, 代价一定是最小的. 与此同时, 我们可以注意到使标记元素连续所需的最小交换次数是「交换前每个标记元素到中间位置的距离之和」与「交换后该距离之和」的差值, 其中「交换后该距离之和」显然是一个定值, 我们可以放到最后来处理.

这样, 我们就可以很自然的想到从 \(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\).

代码并不难实现, 细节也不多, 就不放了.

posted @ 2025-03-24 20:46  Steven1013  阅读(34)  评论(0)    收藏  举报