#include <cstdio>
#include <cstring>
#define maxn 70000
#define LL __int64
int A[maxn], T[maxn];
LL ans;
void merge_sort(int A[], int x, int y) //对区间[x,y)进行排序
{
if(y-x> 1)
{
int m= (y + x)/ 2;
merge_sort(A, x, m); //递归求解
merge_sort(A, m, y);
int p= x, q= m, i= x;
while(p< m || q< y) //只要有一个序列非空,则继续合并
{
if(q>= y || (p< m && A[p]<= A[q])) T[i++]= A[p++]; //这里刚刚没写=WA两次了
else T[i++]= A[q++], ans+= m-p; //m-p代表左区间剩下的元素的个数,剩下的元素都大于A[q]
}
for(int i= x; i< y; i++) A[i]= T[i];// 从辅助空间复制回A数组
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i= 1; i<= n; i++)
scanf("%d",&A[i]);
ans= 0;
merge_sort(A, 1, n+1);
printf("%I64d\n",ans);
}
return 0;
}
给你一列数a1,a2.,..an i<j && ai> aj 算一对逆序对数
分治三步法:
划分问题: 把序列分成元素尽量相等的两半
递归求解: 统计i和j均在左边或者均在右边的逆序对个数
合并问题: 统计i在左边,j在右边的逆序对个数
所以求逆序对时我们只需在归并排序中统计左边序列中比A【q】大的数的个数即可
while(p< m || q< y) 表示两个序列不全为空时继续合并
if(q>= y || (p< m && A[p]<= A[q])) T[i++]= A[p++]; q>=y 表示右边序列已经为空, p< m表示左边序列不为空 该条件为若右边序列为空 或者 右边不为空 &&左边序列不为空&&
右边的小于左边,则把左边的排前面,否则则把右边的排前面,(求逆序对时 ans+= 排右边的数时,左边的序列的数剩余的个数)
注意A[p]<= A[q] 如果不写等于 就会出现 i<j , ai== aj 也判定为逆序对的情况