Description
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。 一个排列中逆序的总数就称为这个排列的逆序数。逆序数是课程线性代数的一个知识点。 现在给定一个排列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称ai和aj为一个逆序,请求出排列的逆序数。
输入格式
第一行为n,表示排列长度。(1=<n<=100000) 第二行有n个整数,依次为排列中的a1,a2,…,an。所有整数均在int范围内。
输出格式
一个整数代表排列的逆序数。
输入样例
4 3 2 3 2
输出样例
3
提示
注意答案的数据范围。
分析:
归并排序的应用。
举个栗子吧,当左半有序部分是4 5 8,右半有序部分是1 3 7时,
1比4小,那么1就比4以及后面的全部数字都小,也就是说逆序对的数量就要加上mid-i+1。
#include<iostream>
#include<algorithm>
using namespace std;
int a[1000010],tmp[1000010];
long long n,cnt;
void mergesort(int l,int r) {
if(l>=r) {
return;
} else {
int mid=l+r>>1;
mergesort(l,mid);
mergesort(mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r) {
if(a[i]<=a[j]) {
tmp[k++]=a[i++];
} else {
tmp[k++]=a[j++];
cnt+=mid-i+1;
}
}
while(i<=mid) {
tmp[k++]=a[i++];
}
while(j<=r) {
tmp[k++]=a[j++];
}
for(i=l,k=0; i<=r; i++) {
a[i]=tmp[k++];
}
}
}
int main() {
cin>>n;
for(int i=0; i<n; ++i) {
cin>>a[i];
}
mergesort(0,n-1);
cout<<cnt;
return 0;
}