给定一串数字,求逆序对数问题。
这样来理解,假设数组中间分开划为两半,并且假设左右分别升序排序,这种情况下,假设左数组范围为 begin 到 q, 右半部分为 q+1到end,令 i = q, j = end, 则当 a[i] > a[j]时,右半部分有 j - (q+1)+1个数和a[i]构成逆序对。然后i, j 向左移动结束之后,就得到两个有序的左右部分的逆序对数;
那么此问题可以使用归并排序,在排序的mrge过程中,按照上述规则记录逆序对数;
// 求逆序对数
#include<iostream>
using namespace std;
int tmp[1005], ans ;
void merge(int a[], int begin, int q, int end) {
int k = end;
int i = q, j = end;
while (i >= begin && j >= q + 1) {
if (a[i] > a[j]) {
tmp[k--] = a[i];
ans += j - (q + 1) + 1;
--i;
}
else {
tmp[k--] = a[j];
--j;
}
}
for (; i >= begin; --i)
tmp[k--] = a[i];
for (; j >= q + 1; --j)
tmp[k--] = a[j];
for (i = begin; i <= end; ++i)
a[i] = tmp[i];
return;
}
void mergesort(int a[], int begin, int end) {
if (begin >= end) return;
int q = (begin + end) >> 1;
mergesort(a, begin, q);
mergesort(a, q + 1, end);
merge(a, begin, q, end);
}
int main()
{
int n, T , num[1005], seq = 1;
cin >> T;
while (seq <= T) {
cin >> n;
for (int i = 0; i < n; ++i)
cin >> num[i];
ans = 0;
mergesort(num, 0, n - 1);
cout << "Scenario #" << seq << ":" << endl;
cout << ans <<endl << endl;
++seq;
}
return 0;
}