求逆序对

本文介绍如何利用归并排序的过程来高效地计算数组中的逆序对数量。通过详细解析归并排序的每一步操作,展示了如何在排序过程中记录逆序对的数量,为解决逆序对问题提供了一种实用的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么归并排序能够求逆序对?
注意归并排序是从小到大的一个过程。是从相邻的两个数开始处理的,对于相邻的两个数,这两个数的交换会增加或者减少一个逆序对(不考虑相等的情况)。对于一个数组内的一部分数字,他们内部的交换不会改变外面的数字的相对逆序对数量。所以,我们只要求每个归并排序的时候的逆序对数量就可以了。

对于两个有序数对的逆序对,A1,A2。我们只需要在A2中每个元素中找到A1中比它大的就可以了。在排序的时候,遇到左边 i比右边的
j 大的时候,我们就要考虑这个时候的逆序对,应该是mid到i之间的所有元素。

我们现在考虑这种情况是不是全部的逆序对。我们注意,当i>j的时候,我们填入的是j,并不是i,所以i的光标位置是不动的。因为我们插入是按照大小的顺序,所以i中比j位置大的数字一定还没有插入,所以这种情况就包含了所有的逆序对.

#include <iostream>
using namespace std;
const int size = 100005;
const int lgsize = 20;
int temp[lgsize][size];
int cnt=0;

void mergesort(int lo,int hi,int depth){
    if(lo>=hi) return ;
    int mid = (lo+hi)/2;
    mergesort(lo,mid,depth+1);
    mergesort(mid+1,hi,depth+1);
    int i = lo ;
    int j = mid+1;
    for(int k = lo ; k <= hi ; k++){
        if(i>mid){ 
            temp[depth][k]=temp[depth+1][j++];
        }
        else if (j>hi) {
            temp[depth][k] = temp[depth+1][i++];
            //cnt+=(mid-i++-1);
        }
        else if(temp[depth+1][i]>temp[depth+1][j]){
         temp[depth][k]=temp[depth+1][j++];
         cnt+=(mid-i+1);//只算i才行
        }
        else{ 
            temp[depth][k]=temp[depth+1][i++];
        }
    }
}

int main(int argc, char const *argv[])
{
    int N;
    int K;
    while(cin>>N>>K){
        cnt = 0;
        for(int i = 0 ; i < N ; i++){
            cin>>temp[0][i];
        }
        for(int i = 1 ; i < lgsize;i++){
            for(int j = 0 ; j < N ; j++){
                temp[i][j]=temp[0][j];
            }
        }
        mergesort(0,N-1,1);//注意是n-1
    }
    return 0;
}

特别注意相等的处理手法,只有i位置大于J位置才增加逆序对的数目,否则把i位置的填进去(就是相等的时候把左边的填进去).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值