归并分治

归并分治

  • 本文用于整理 ACM 博弈论相关知识点与题目,方便自己和队友查阅。
  • 持续更新中……

一、什么是归并分治

归并分治是分治思想最典型的应用之一,核心流程是:

  1. 分(Divide):把序列从中间切成两半
  2. 治(Conquer):递归处理左半和右半
  3. 合(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 分治、点分治
posted @ 2026-10-10 11:34  leaderling  阅读(8)  评论(0)    收藏  举报