难度:进阶。题目原型为 AOJ ALDS1_5_B Merge Sort。本题的考点是在归并排序的合并阶段统计比较次数:除了把数组排好,还要记录排序过程中一共比较了多少次,理解归并排序每一层做了多少工作。
目标
完成本题后,你应该能够:
- 用归并排序完成排序,并输出排序结果;
- 正确统计合并过程中的比较次数;
- 说明「比较次数」的定义如何随实现方式(哨兵 vs. 显式拷贝)变化。
前置知识
- 归并排序的递归与合并过程;
- 双指针合并两个有序数组。
题目
读入 n 和 n 个整数,用归并排序把它们从小到大排序,输出排序后的数组与归并过程中的比较次数。
输入格式
- 第一行一个整数
n; - 第二行
n个整数,表示待排序序列a。
输出格式
- 第一行:排序后的
n个整数,从小到大排列,相邻整数用一个空格隔开; - 第二行:一个整数,表示归并排序过程中的比较次数。
数据范围
| 项目 | 范围 |
|---|---|
序列长度 n | 1 ≤ n ≤ 5 × 10⁵ |
| 元素值 | −10⁹ ≤ a[i] ≤ 10⁹ |
样例
样例输入
input
10
8 5 9 2 6 3 7 1 10 4样例输出
output
1 2 3 4 5 6 7 8 9 10
34样例解释
序列 8 5 9 2 6 3 7 1 10 4 归并排序后为 1 2 3 4 5 6 7 8 9 10。采用「哨兵 + 每次写入计一次比较」的计数方式时,整个归并过程共比较 34 次。
如何验证
先安装 Node.js、pnpm 和支持 C++17 的编译器。
powershell
# 已进入本 Lab 目录
make doctor
make run
make run CASE=001-sample
make interactive
make scoreWindows 没有安装 Make 时,在仓库根目录使用等价的 pnpm 入口:
powershell
pnpm lab:run -- labs/chapter-11/exercise/E-11-06-merge-sort-count
pnpm lab:score -- labs/chapter-11/exercise/E-11-06-merge-sort-count标准输出参与判题,调试信息请写入标准错误。
完成清单
思考题
- 采用哨兵写法时,比较次数为什么等于「所有合并操作写入元素的总次数」?
- 如果改用
while循环 + 显式拷贝剩余元素的写法,比较次数会如何变化?会不会比哨兵写法少?