逆序对的nlogn方法,改进后的归并排序
给定排列P,求排列的逆序对数量。
P的长度<=100000。
要求O(nlogn)
定义归并排序过程Merge(l,r)
Merge(l,r)
Merge(l,mid)
Merge(mid+1,r)
Count(l,mid,mid+1,r)
只需要考虑左右两段之间造成的逆序对,段内的逆序对由递归解决
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int a[8] = {4, 3, 5, 2, 6, 1, 7, 4};
int c[8] = {0};
int Count(int al, int ar, int bl, int br){
int re = 0, i = 0, j = 0;
while(al+i <= ar && bl+j <= br){
if (a[al+i] <= a[bl+j]){
c[al+i+j] = a[al+i];
++i;
re += j;
}
else{
c[al+i+j] = a[bl+j];
++j;
}
}
if (al+i > ar && bl+j <= br){
while(bl+j <= br){
c[al+i+j] = a[bl+j];
++j;
}
}
if (al+i <= ar && bl+j > br){
while(al+i <= ar){
c[al+i+j] = a[al+i];
++i;
re += j;
}
}
while(al<=br){
a[al] = c[al];
al++;
}
return re;
}
int MergeSort(int l, int r){
if(l>=r) return 0;
int m = (l+r)>>1;
int re = MergeSort(l, m) + MergeSort(m+1, r);
re += Count(l, m, m+1, r);
return re;
}
#define REP(i,n) for(int i=0;i<n;i++)
int main()
{
REP(i,8) printf("%d%c", a[i], i<7?' ':'\n');
int cnt = MergeSort(0, 7);
printf("%d\n", cnt);
REP(i,8) printf("%d%c", a[i], i<7?' ':'\n');
return 0;
}