题目链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1311
最坏情况下,逆序数对的数量为 ( n − 1 ) + ( n − 2 ) + . . . + 1 = n ( n − 1 ) 2 (n-1)+(n-2)+...+1=\frac{n(n-1)}{2} (n−1)+(n−2)+...+1=2n(n−1),可能会爆掉 int。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int N = 100010;
int a[N], tmp[N];
ll res;
// 将[l1,r1]和[l2,r2]两个有序区间合并为一个有序区间
void Merge(int l1, int r1, int l2, int r2)
{
int i = l1, j = l2, k = l1;
while (i <= r1 && j <= r2)
{
if (a[i] > a[j])
{
res += r1 - i + 1;
tmp[k++] = a[j++];
}
else
{
tmp[k++] = a[i++];
}
}
while (i <= r1)
{
tmp[k++] = a[i++];
}
while (j <= r2)
{
tmp[k++] = a[j++];
}
for (int i = l1; i <= r2; i++)
{
a[i] = tmp[i];
}
}
void MergeSort(int left, int right)
{
// 若当前区间只有一个数或没有数,则直接return
if (left >= right) return;
// 将[left,right]划分为[left,mid]和[mid+1,right]两个子问题
int mid = left + right >> 1;
MergeSort(left, mid);
MergeSort(mid + 1, right);
// 将[left,mid]和[mid+1,right]两个有序区间合并为一个有序区间
Merge(left, mid, mid + 1, right);
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
MergeSort(0, n - 1);
printf("%lld\n", res);
return 0;
}