归并排序与逆序对
Skyzhou666 · · 算法·理论
归并排序
大概思路就是二分先去划分,然后每一层都保证左边和右边是严格排序的再合并,利用递归
模板:
void mergeSort(int l, int r)
{
if(l == r) return;
int mid = (l+r)/2, i = l, j = mid+1, k = l;
mergeSort(l, mid);
mergeSort(mid+1, r);
while(i <= mid && j <= r)
if(s[i] <= s[j]) tmp[k++] = s[i++];
else tmp[k++] = s[j++];
while(i <= mid) tmp[k++] = s[i++];
while(j <= r) tmp[k++] = s[j++];
for(int x = l; x <= r; x++) s[x] = tmp[x];
}
应用场景一 求逆序对
P1908 逆序对
利用归并排序的特性,每次归并
AC代码(参考题解)
#include <iostream>
#include <algorithm>
#define MAXN 500001
using namespace std;
int s[MAXN], tmp[MAXN];
long long ans;
void mergeSort(int l, int r)
{
if(l == r) return;
int mid = (l+r)/2, i = l, j = mid+1, k = l;
mergeSort(l, mid);
mergeSort(mid+1, r);
while(i <= mid && j <= r)
if(s[i] <= s[j]) tmp[k++] = s[i++];
else tmp[k++] = s[j++], ans += mid - i + 1;
while(i <= mid) tmp[k++] = s[i++];
while(j <= r) tmp[k++] = s[j++];
for(int x = l; x <= r; x++) s[x] = tmp[x];
}
int main()
{
int n;
cin >> n;
for(int x = 1; x <= n; x++) scanf("%d", &s[x]);
mergeSort(1, n);
printf("%lld\n", ans);
return 0;
}
参考资料:
动图讲解
P1908题解