逆序对 (归并排序)

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


你可能感兴趣的:(分治)