码迷,mamicode.com
首页 > 其他好文 > 详细

逆序对的两种求法

时间:2019-11-23 16:08:51      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:分治思想   lin   mat   ret   i++   math   合并   amp   长度   

逆序对

对于一个数论\(a_{1},a_{2}......a_{n}\),定义有一对序列\({i,j}\),当且仅当\(i<j\)\(a_{i}>a_{j}\)为逆序对

归并排序

归并排序是基于分治思想进行的,把区间\([l,r]\)拆分成\([l,mid]\)\([mid+1,r]\)两部分,分治下去进行排序,每次合并的复杂度就是当前[l,r]的长度,进行\(log_{2}n\)次分治,总长度为n,则
归并排序的复杂度为\(O(nlog_{2}n)\)

归并排序写法

void MergeSort(int l,int r){
    if(l == r)return;
    int mid = (l + r) >> 1;
    MergeSort(l, mid);//左边
    MergeSort(mid+1,r);//右边
    int i = l,j = mid + 1, t = l;//i是左边的,j是右边的
    while(i <= mid && j <= r){
        if(a[i] <= a[j])b[t++] = a[i++];//左边小
        else b[t++] = a[j++];
    }
    while(i <= mid)b[t++] = a[i++];//右边部分多
    while(j <= r)b[t++] = a[j++];//左边部分多
    for(int k = l;k <= r; k++)a[k] = b[k];//及时更新
}

而对于求逆序对,由于合并所以左边和右边都是一组有序的数论。
左区间中剩下没加入的合并元素部分的一定就比右区间大
所以,在

else b[t++] = a[j++];

部分加一个ans += mid-i+1

则基于归并排序的求逆序对模板为

void MergeSort(int l,int r){
    if(l == r)return;
    int mid = (l + r) >> 1;
    MergeSort(l, mid);//左边
    MergeSort(mid+1,r);//右边
    int i = l,j = mid + 1, t = l;//i是左边的,j是右边的
    while(i <= mid && j <= r){
        if(a[i] <= a[j])b[t++] = a[i++];//左边小
        else b[t++] = a[j++],ans += mid - i + 1;
    }
    while(i <= mid)b[t++] = a[i++];//右边部分多
    while(j <= r)b[t++] = a[j++];//左边部分多
    for(int k = l;k <= r; k++)a[k] = b[k];//及时更新
}

树状数组

逆序对的两种求法

标签:分治思想   lin   mat   ret   i++   math   合并   amp   长度   

原文地址:https://www.cnblogs.com/Emcikem/p/11918141.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!