1 条题解
-
0
题意简述
给定一个 到 的排列 。
若对于所有 满足 或 ,则称排列是 简单 的。
每次操作可以交换任意两个位置 的值。问最少需要多少次操作,能使排列变成 简单 排列。
观察 1
任何一个排列可以分解为若干个不相交的循环。
例如 对应的映射:- 是一个长度为 的循环。
- 是一个长度为 的循环。
读取排列后,可以在 时间内遍历所有循环。
观察 2
我们对“简单排列”的定义重述一下:
原定义: 或 。
等价地说:- 若 ,则是长度为 的循环。
- 若 ,并且 ,则 和 形成一个长度为 的循环。
因此,简单排列等价于每个循环的长度不超过 。
当我们在一个循环内交换两个元素时:
- 假设当前循环长度为 。
- 交换两个不同的元素(它们属于这个循环),则原来的一个循环会分裂成 两个 循环,它们的长度之和为 。
观察 3
对于一个长度为 的循环,我们想把它拆成若干个长度不超过 的循环。
每次操作可以(通过合适的交换)让循环长度减少 。
操作次数为 。为什么?
- 长度为 的循环不需要操作。
- 长度为 的循环已经长度 ,不需要操作。
- 长度为 的循环:交换其中两个元素,变成 (两个循环),需要 次操作。,正确。
- 长度为 的循环:先操作一次,变成 ,需要 次操作。公式:,正确。
- 长度为 的循环:先操作一次,变成 ,再对剩下的长度 操作一次,变成 ,共 次。公式:,正确。
可以严格证明:每次操作最多将一个大循环中长度为 的部分“切出来”,至少减少 的长度,直到剩下 。
观察 4
不同循环的操作是独立的。
$$\text{answer} = \sum_{\text{每个循环}} \left\lfloor \frac{\text{len} - 1}{2} \right\rfloor $$
因为交换操作会影响元素的位置,但如果我们总是在同一个循环内部交换,它只会分裂该循环,不会影响其他循环。
因此,最终答案是所有循环的答案之和:
总复杂度
即可:遍历数组,标记已访问元素,计算每个循环的长度,累加 到答案。
示例验证
例 3:
- 循环:,长度
- 操作次数: ✅
例 4:
- 循环:,长度
- 操作次数: ✅
例 6:
- 循环 :,长度 → 次
- 循环 :,长度 → 次
- 总共 次 ✅
- 1
信息
- ID
- 7033
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8.5
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者