【AcWing刷题日记】逆序对数量

该博客介绍了一种利用归并排序算法解决逆序对问题的方法。通过在归并过程中添加计数操作,将时间复杂度降低到O(NlogN),避免了O(N^2)的复杂度。考虑到数据范围可能达到100000,使用long long类型存储计算结果以防止溢出。代码实现中展示了如何在归并排序递归过程中计算逆序对,并给出了完整的C++代码示例。
摘要由CSDN通过智能技术生成

题目

归并排序的变种
刷题链接:https://www.acwing.com/problem/content/790/
在这里插入图片描述

分析

逆序对的解决方案当然可以一个元素和其他所有元素进行比较,但这样复杂度过高,会达到O(N2

利用归并排序的复杂度,只需在其过程中添加一个计数操作即可

分为三种情况,其中黄色的情况(在两侧)是需要在归并的过程中处理的数据。两个数据q[i]和q[j]比较,如果发现前者大,那么(L,mid)区间内,q[i]及其后边的数据都比q[j]大,而且位置处于j的前边,都是逆序对。

一切都是因为给数据了一个规则,从无序的N2复杂度就变为了NlogN。这个题是给了一个有序的前提
在这里插入图片描述

这个题还有个数据范围的考虑,由于是100000的数据范围。因此考虑最坏的情况:数据逆序排列,n个数(n,n-1,n-2…2,1)–> 逆序对的数量就是(n-1)+(n-2)+…1 = n(n-1)/2

因此n2=1010/2 的范围,超过了int存储范围,因此采用long long 存储计算结果。

#include<iostream>
using namespace std;

typedef long long LL;
const int N = 100010;
int q[N], tmp[N];

LL mergesort(int l, int r){
    if(l>=r)return 0;  //对于归并来说,这里可以写 == 号
    int mid = l+r >> 1;  //整除2
    LL res = mergesort(l, mid) + mergesort(mid+1, r);
    
    int i=l, j=mid+1, k=0;
    while(i<=mid && j<=r){
        if(q[i]>q[j]){
            res += mid - i + 1;
            tmp[k++] = q[j++];
        }
        else tmp[k++] = q[i++];
    }
    //扫尾
    while(i<=mid)tmp[k++] = q[i++];
    while(j<=r)tmp[k++] = q[j++];
    
    //物归原主
    for(int i=l, j=0; i<= r;i++,j++) q[i] = tmp[j];
    
    return res;
}


int main(){
    int n;
    cin >> n;
    for(int i=0;i<n;i++)cin >> q[i];
    
    cout<<mergesort(0, n-1)<<endl;
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小雨的杰拉多尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值