逆序对的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; }