#include<stdio.h> //求逆序数
#define MAX 50001
/*
算法思想:
利用归并排序的算法思想:归并排序是将带排序序列分为若干个子序列,每个子序列是有序的,
然后再把有序的子序列逐步合并成为整体有序序列
因此可利用归并排序的算法框架,依次计算小序列的逆序数,最终求得大序列的逆序数
*/
long long count;
int a[MAX], b[MAX];
void Merge(int left, int middle, int right)
{
int i = left, j = middle + 1, k = left;
while (i <= middle&&j <= right)
{
if (a[i] <= a[j])
b[k++] = a[i++];
else
{
count += j - k;
//计算小序列的逆序数(此时a[i]>a[j],由于a[i]到a[middle]是升序排列,故逆序数的增量应为middle-i+1,
//初始时j=middle+1,k=i,当k和i同时++时(此时j不变),逆序数的增量减少,当k和j同时++时,逆序数增量不变,
//因此增量为j-k(k永远不超过j)
b[k++] = a[j++];
}
}
while (i <= middle)
b[k++] = a[i++];
while (j <= right)
b[k++] = a[j++];
for (i = left; i <= right; i++)
a[i] = b[i];
}
void MergeSort(int left, int right)
{
int middle;
if (left < right)
{
middle = (left + right) / 2;
MergeSort(left, middle);
MergeSort(middle + 1, right);
Merge(left, middle, right);
}
}
int main()
{
int n, i;
scanf("%d", &n);
for (i = 0; i < n; i++)
scanf("%d", a + i);
count = 0;
MergeSort(0, n - 1);
printf("%d\n", count);
return 0;
}
51Nod 逆序数
最新推荐文章于 2022-02-11 11:43:21 发布