由二分法,一个初始数列最终会被分成 n 个单个项,相当于 n 个排好序的数列。
对于已排好序的两个子数列,长度分别为L1,L2,每一次比较两个数列剩余项中的首项,并将较大项或较小项整合进入原数列,并从相应子数列中剔除,则最多经过L1+L2次比较,可以将原数列对应区段完成单调排序。
模板一:

#include<iostream> #include<cmath> #include<algorithm> using namespace std; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } void merge(int x[],int left,int mid,int right) { int temp1[5005],temp2[5005]; int n1=mid-left; int n2=right-mid; for(int i=0;i<n1;i++) temp1[i]=x[left+i]; for(int i=0;i<n2;i++) temp2[i]=x[mid+i]; temp1[n1]=500000; temp2[n2]=500000; int i=0,j=0; for(int k=left;k<right;k++) if(temp1[i]<=temp2[j]) x[k]=temp1[i++]; else x[k]=temp2[j++]; } void msort(int x[],int left,int right) // right = a + 1 { if(left+1<right) { int mid=(left+right)/2; msort(x,left,mid); msort(x,mid,right); merge(x,left,mid,right); } } int main() { int a; a=read(); int n[a]; for(int i=0;i<a;i++) n[i]=read(); msort(n,0,a); for(int i=0;i<a;i++) { if(i) cout<<" "; cout<<n[i]; } return 0; }
模板二(2021/2/3 update):
(其中ans是记录数列中逆序对个数)

#include<iostream> #include<cstdio> using namespace std; const int range=5e5+5; int n[range]; long long ans; int temp1[range],temp2[range]; void msort(int l,int r) { int mid=(l+r)>>1; if(l==r) return ; else { msort(l,mid); msort(mid+1,r); } int l1=l,l2=mid+1; for(int i=l;i<=mid;i++) temp1[i]=n[i]; for(int i=mid+1;i<=r;i++) temp2[i]=n[i]; int i; for(i=l;l1<=mid&&l2<=r;i++) if(temp1[l1]>temp2[l2]) { ans+=mid-l1+1; n[i]=temp2[l2]; l2++; } else { n[i]=temp1[l1]; l1++; } while(l1<=mid) n[i++]=temp1[l1++]; while(l2<=r) n[i++]=temp2[l2++]; } int main() { int a; scanf("%d",&a); for(int i=1;i<=a;i++) scanf("%d",&n[i]); msort(1,a); cout<<ans; return 0; }