#include<bits/stdc++.h>
using namespace std;
int n;
long long cnt = 0;
const int N = 5e5+5;
int a[N],b[N];
void Mergesort(int l,int r);
void Merge(int l,int mid,int r);
int main(){
cin>>n;
for(int i = 0;i<n;i++)cin>>a[i];
Mergesort(0,n-1);
cout<<cnt;
return 0;
}
void Mergesort(int l,int r){
if(l<r){
int mid = (l+r)/2;
Mergesort(l,mid);
Mergesort(mid+1,r);
Merge(l,mid,r);
}
}
void Merge(int l,int mid,int r){
int i = l, j = mid+1, t = 0; //t来记录b数组内添加的元素个数,方便后面复制到a数组排序;
while(i<=mid&&j<=r){
if(a[j]<a[i]){
b[t++]=a[j++];
cnt+=mid-i+1;
}
else b[t++]=a[i++];
}
while(i<=mid)b[t++]=a[i++];
while(j<=r)b[t++]=a[j++];
for(int i = 0;i<t;i++)a[l+i]=b[i];
}
归并排序大致可以分为三个步骤:分组 排序 和归并,在上面代码中,Mergesort函数不断递归进行分组,知道只剩下一个元素(即l=r了),然后调用Merge函数,排序的同时进行归并
比如说对 3 2 7 6 1 4 5 1进行归并排序
排序前有: [3] [2] [7] [6] [1] [4] [5] [1] 每一组数据都只有1个元素,且都是有序的
第一次有:[2 3] [6 7] [1 4] [1 5] 仍是有序的
第二次有:[2 3 6 7] [1 1 4 5]
第三次有: [1 1 2 3 4 5 6 7]
排序时要确保左右两边都是有序的才行,每次排序复杂度为O(N),一共有log2N次排序,总时间复杂度为O(Nlog2N)
上面的代码是洛谷习题逆序对的题解