归并分治
归并分治
- 本文用于整理 ACM 博弈论相关知识点与题目,方便自己和队友查阅。
- 持续更新中……
一、什么是归并分治
归并分治是分治思想最典型的应用之一,核心流程是:
- 分(Divide):把序列从中间切成两半
- 治(Conquer):递归处理左半和右半
- 合(Merge):把两个有序子序列合并成一个有序序列
归并排序就是归并分治的直接产物。但归并分治真正的价值在于:在合并的过程中,可以顺便统计一些“跨左右”的信息。
最常见的应用就是统计逆序对。
二、归并排序模板
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int a[N], tmp[N];
void mergeSort(int l, int r)
{
if (l >= r) return;
int mid = (l + r) >> 1;
mergeSort(l, mid);
mergeSort(mid + 1, r);
// 合并两个有序区间 [l, mid] 和 [mid+1, r]
int i = l, j = mid + 1, k = l;
while (i <= mid && j <= r)
{
if (a[i] <= a[j]) tmp[k++] = a[i++];
else tmp[k++] = a[j++];
}
while (i <= mid) tmp[k++] = a[i++];
while (j <= r) tmp[k++] = a[j++];
for (int i = l; i <= r; i++)
a[i] = tmp[i];
}
三、归并分治原理
1)思考一个问题在大范围上的答案,是否等于,左部分的答案 + 右部分的答案 + 跨越左右产生的答案
2)计算"跨越左右产生的答案"时,如果加上左右各自有序这个设定,是否能简便计算
3)如果以上两点都成立,那么该问题很可能能被归并分治解决
*在求解的过程中加入归并排序过程即可
四、典型应用
1. 计算数组的小和
- 模型:求每个数左侧 ≤ 它的所有数之和,累加起来
- 关键:归并合并两个有序区间时,用双指针维护左半 ≤
arr[j]的元素和sum - 复杂度:O(n log n)
七、总结
| 要点 | 内容 |
|---|---|
| 核心思想 | 分治:分左右、递归、合并 |
| 模板 | 双指针合并两个有序区间 |
| 逆序对统计 | 右半元素被选中时,左半剩余个数就是贡献 |
| 复杂度 | O(n log n) |
| 扩展 | CDQ 分治、点分治 |

浙公网安备 33010602011771号