思路
1.笨方法 o(n^2)
2.分治 o(nlogn)
(1).将数组分成两份 求两部分的逆序数
(2).再算有多少逆序是从左边选择一个逆序,再从右边选择一个逆序组成的。o(n)
/*
求全排列的逆序数
*/
#include <bits/stdc++.h>
using namespace std;
int MergeAccount(int a[] , int left , int mid , int right);
int Merge(int a[] , int left , int right){
int mid = left+right>>1;
int count = 0;
if(left<right){
count+=Merge(a , left , mid);
count+=Merge(a , mid+1 , right);
count+=MergeAccount(a , left , mid , right);
}
return count;
}
int MergeAccount(int a[] , int left , int mid , int right){
int count = 0; //计数
int len1=mid-left+1,len2=right-mid; //左右区间的长度
int al[len1],ar[len2]; //clone
for(int i=0;i<len1;i++)al[i] = a[left+i];
for(int i=0;i<len2;i++)ar[i] = a[mid+1+i];
int i=0,j=0;
for(int k=left;k<=right;k++){
if(i >= len1){ //归并最后while的作用 i已经进入完了 还剩下j
a[k] = ar[j];
j++;
}else if(j >= len2){ //j已经进入完了 还剩下i
a[k] = al[i];
i++;
}else if(al[i] > ar[j]){
a[k] = al[i];
i++;
count+=len2-j;
}else {
a[k] = ar[j];
j++;
}
}
return count;
}
int main()
{
int a[100];
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
cout<<Merge(a , 1 , n)<<endl;
return 0;
}