基本步骤:
1、分界点 mid=(l+r)/2
2、递归排序(left,right)
3、合二为一
#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#include<algorithm>
using namespace std;
inline ll read()
{
ll x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1; ch=getchar(); }
while('0'<=ch&&ch<='9') x=x*10+ch-'0', ch=getchar();
return f*x;
}
const int N = 1e5+5;
int n,a[N],L[N/2+2],R[N/2+2];
void mergesort(int l,int r)
{
if(l+1>=r) return ;
int mid=l+r>>1;
mergesort(l,mid); mergesort(mid,r);
int n1=mid-l,n2=r-mid;//n1左边个数,n2右边个数
for(int i=0;i<n1;i++) L[i]=a[l+i];//[l,mid)
for(int i=0;i<n2;i++) R[i]=a[mid+i];//[mid,r)
L[n1]=R[n2]=inf;//哨兵,处理边界
int i=0,j=0;
for(int k=l;k<r;k++)
{
if(L[i]<=R[j]) a[k]=L[i++];
else a[k]=R[j++];
}
}
int main()
{
n=read();
for(int i=0;i<n;i++) a[i]=read();
mergesort(0,n);//[0,n)
for(int i=0;i<n;i++) cout<<a[i]<<" ";
return 0;
}
巧用归并排序:求数组中逆序对的个数
利用归并排序的特性,L数组中的数相对与R数组一定位于原数组的左边,那么如果R中的数小于L中的数就会产生逆序对,又因为L数组和R数组本身是有序的,R中的某个数R[j]小于L中的某个数L[i],那么(L[i],R[j])是一个逆序对,同时R[j]与L[i]后面的数一定也是逆序对,因为L[i]<=L[i+1],而R[j]<L[i],所以R[j]<L[i+1]<=L[i+2]…<=L[n1-1](一直到L数组末尾)
所以R[j]与L数组产生的总共的逆序对数为n1-i;
#include<cstdio>
#include<cmath>
#include<ctime>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#define ll long long
#define ull unsigned long long
#define up_b upper_bound
#define low_b lower_bound
#define m_p make_pair
#define mem(a) memset(a,0,sizeof(a))
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define inf 0x3f3f3f3f
#include<algorithm>
using namespace std;
inline ll read()
{
ll x=0,f=1; char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1; ch=getchar(); }
while('0'<=ch&&ch<='9') x=x*10+ch-'0', ch=getchar();
return f*x;
}
const int N = 5e5+5;
int n,a[N],L[N/2+2],R[N/2+2];
ll ans=0;
void mergesort(int l,int r)
{
if(l+1>=r) return ;
int mid=l+r>>1;
mergesort(l,mid); mergesort(mid,r);
int n1=mid-l,n2=r-mid;//n1左边个数,n2右边个数
for(int i=0;i<n1;i++) L[i]=a[l+i];//[l,mid)
for(int i=0;i<n2;i++) R[i]=a[mid+i];//[mid,r)
L[n1]=R[n2]=inf;//哨兵,处理边界
int i=0,j=0;
for(int k=l;k<r;k++)
{
if(L[i]<=R[j]) a[k]=L[i++];
else a[k]=R[j++], ans+=n1-i;
}
}
int main()
{
n=read();
for(int i=0;i<n;i++) a[i]=read();
mergesort(0,n);//[0,n)
// for(int i=0;i<n;i++) cout<<a[i]<<" ";
cout<<ans<<endl;
return 0;
}