1 条题解
-
0
保持二分的比较结果
思路
先在原排列上完整模拟题目指定的二分过程,记最终下标为 ,数字 的原位置为 。如果两者相同,原排列已经满足要求。否则,将 与 交换即可。
关键是交换以后,二分仍然走原来的路径。这样最终下标仍为 ,但该位置的值已经变成 。
做法
读取排列时找到 的位置。按照题面使用 ,在 时更新左端点,模拟直到左右端点相邻。
若最后 ,输出零次操作;否则输出一次操作,交换 与 。题目允许至多两次,但并不要求一定使用两次。
正确性证明
若 ,则 一定是某次比较后更新得到的左端点,所以交换前 。另一个交换位置原来存放的就是 。交换后,这两个位置对条件“当前位置的值不超过 ”的判断均未改变,其他位置也没有变化。因此二分每一步选择同一个分支,最后仍停在 。
若 且 ,同样可用上述比较值不变的论证。
最后考虑 且 。在循环中,中点总大于当前左端点,所以位置 从未作为中点被读取;位置 也不可能被读取,否则由于其值为 ,左端点会被更新到至少 ,与 矛盾。因此交换的两个位置均不在原二分读取路径上,所有已读取值不变,路径仍然不变。
综上,交换后二分仍停在 ,且 。如果原来已经满足要求,则零次操作显然合法。算法最多使用一次交换,符合题目的限制。
复杂度
读取排列并找到 使用 时间,模拟二分使用 时间,总时间为 。存储排列需要 空间。
部分分思路
极小规模可以枚举最终排列,检查二分结果,并通过置换的循环分解判断能否在两次交换内从原排列得到它。依次把每个位置换成目标值,就能构造最少交换序列。这个方法需要阶乘数量的枚举。
中等规模可以先试零次交换,再枚举每一对位置,交换后实际运行二分。上述定理保证一定存在至多一次交换的解,所以这一枚举完整正确,时间复杂度为 。
当 时,把 放到首位后,其余中点上的值都大于 ,二分停在首位;当 时,所有比较都向右走,最终停在末位,只需把 放到末位。这两个端点情形都可以直接把 放到下标 ,不必分析任意排列的二分路径。
信息
- ID
- 1690
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者