标签: 递归、归并排序
【题解】
数据量很大,普通的比较很容易超时。
题意是比较找出 a i a_i ai > a j a_j aj且 i < j 的有序对,因此只需比较 a i a_i ai 和后面的数即可,所以可以用归并排序,在合并的时候比较。
注意: 记录逆序对的数目ans要用long long 型,虽然数据量n在int范围内,但是比较结果很容易超过int的存储范围。
【代码】
#include <iostream>
using namespace std;
int n, a[500005], tmp[500005]; //a是原序对,tmp是临时存储序对
long long ans = 0; //逆序对的数目,要用long long型
void merge(int low, int high) //归并排序
{
if (low == high) return; //递归结束条件
int mid = (low + high) / 2;
merge(low, mid); //左递归排序
merge(mid + 1, high); //右递归排序
int i = low;
int j = mid + 1;
int l = low;
while (i <= mid&&j <= high)
{
if (a[i] > a[j]) {
ans += high - j + 1; //当a[i] > a[j]时,j后面的数也都小于a[i]
tmp[l++] = a[i++];
}
else {
tmp[l++] = a[j++];
}
}
while (i <= mid) tmp[l++] = a[i++];
while (j <= high) tmp[l++] = a[j++];
for (int k = low; k <= high; k++)
a[k] = tmp[k];
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
scanf("%d", &a[i]);
merge(0, n - 1);
printf("%lld\n", ans); //输出long long型ans
return 0;
}