逆序对
思想
-
5 4 3 2 1 逆序对是一个数字和后边每一个比它小的数字都构成一个逆序对
-
在归并过程中分为三类
- 两个数字在区间左边求逆序对:直接返回merge_sort()
- 两个数字在区间右边求逆序对: 直接返回merge_sort()
- 两个数字在区间两边求逆序对: 在归并过程中,右边数组中每加入一个数,都把左边i指针所指的值到左边区间最后端点的个数加上
特点
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int q[N];
int tmp[N];
int n;
LL merge_sort(int q[], int l, int r)
{
if (l >= r) return 0; //res 最深处递归返回值是0. res += mid - i + 1;会逐层返回
int mid = l + r >> 1;
LL res = merge_sort(q, l, mid) + merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
{
if (q[i] <= q[j])
{
tmp[k++] = q[i++];
}
else {
tmp[k++] = q[j++];
res += mid - i + 1; //求当前合并区间的逆序对并加到总数上
}
}
//下边两个while最多只执行一个
while(i <= mid)
{
tmp[k++] = q[i++];
}
while (j <= r)
{
tmp[k++] = q[j++];
}
for (int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];
return res;
}
int main()
{
cin >> n;
for (int i = 0; i <= n; i++) cin >> q[i];
cout << merge_sort(q, 0, n - 1);
return 0;
}