【题目描述】
给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。
【输入】
第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。
【输出】
所有逆序对总数。
【解题思路】
本来采用双层循环试了下,果然超时了,甚至超出int类型数据范围了。说明必须采用归并排序了,但是对于归并排序要如何计数呢。参考了其他人的解答,是在归并过程中累加的,即已经排序好的数组,若 a i ai ai比 a j aj aj大,那说明在前半段数组中, a i ai ai之后的 m i d − i + 1 mid-i+1 mid−i+1个数据均为逆序数字,进行累加。
【解题代码】
#include <iostream>
using namespace std;
#define maxN 500005
long long NumChange = 0;
int a[maxN],tmp[maxN];
void MergeSort(int l, int mid, int r) {
int i = l, j = mid + 1, index = 0;
while (i <= mid && j <= r) {
if (a[i] <= a[j]) {
tmp[index++] = a[i++];
}
else {
NumChange += mid - i + 1; //若a[i]>a[j],则说明有mid-i+1个数字为逆序,进行累加
tmp[index++] = a[j++];
}
}
while (i <= mid) tmp[index++] = a[i++];
while (j <= mid) tmp[index++] = a[j++];
for (int i = 0; i < index; i++) {
a[l + i] = tmp[i];
}
}
void Merge_up2down( int l, int r) {
int mid;
if (l >= r) return;
mid = (l + r) / 2;
//先分解为左右两个区间
Merge_up2down(l, mid);
Merge_up2down(mid + 1, r);
//后调用MergeSort函数进行排序
MergeSort(l, mid, r);
}
int main() {
int N;
cin >> N;
for (int i = 0; i < N; i++) {
cin >> a[i];
}
Merge_up2down(0, N-1);
cout << NumChange;
return 0;
}