在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。
Input
第1行:N,N为序列的长度(n <= 50000)第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)
Output
输出逆序数
Input示例
4
2
4
3
1
Output示例
4
链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1019
思路:今天一天都在做用归并求逆序数的题目,这道题和小朋友排队不同的是只是简单的求每个数的逆序数之和。也就是说只要在判定前面的大于后面的时候进行计算即可。
代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
int nix[55000], cnt[55000];
long long ans = 0;
int MergeSort(int first, int last)
{
if(first < last)
{
int mid = (first + last)/2;
MergeSort(first,mid);
MergeSort(mid+1,last);
int temp = first;
int p = first, q = mid+1;
while(p <= mid && q <= last)
{
if(nix[p] <= nix[q])
cnt[temp++] = nix[p++];
else
{
cnt[temp++] = nix[q++];
ans += (mid - p + 1);
}
}
while(q <= last)
cnt[temp++] = nix[q++];
while(p <= mid)
cnt[temp++] = nix[p++];
for(int i=first; i<=last; i++)
nix[i] = cnt[i];
}
return 0;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0; i<n; i++)
cin >> nix[i];
memset(cnt, 0,sizeof cnt);
ans = 0;
MergeSort(0,n-1);
cout << ans << endl;
}
return 0;
}