ACwing 788 逆序对数量 分治法

题目大意:

现有一个n长的无序数列,并且定义:若i<j,a[i]>a[j],则称无序对<a[i],a[j]>是逆序对。现求数列中是有多少逆序对。

题目解析:

大致思路:

利用归并排序的思想,将其分为若干个小区间(长度为1),每两个区间内前后对比判断逆序对(1、2为一组,3、4为一组......以此类推),然后进行排序合并,这样每个合并后的区间内虽然顺序改变过但在改变之前就已经进行过统计,并且顺序的改变只是在合并后的区间内,区间之间并没有进行过改变,所以仍可以利用以上步骤进行统计。

踩过的坑:

因为每个长度大于等于2的区间都是排过序逇小区间,所以在找到一个满足的后,a[i]到a[mid]都是满足的,所以直接cnt+=mid-i+1。

还有就是统计出来的个数会爆int,所以得用long long。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long 
#define in(x) scanf("%d",&x)
#define in64(x) scanf("%lld",&x)
#define debug(x) cerr<<#x<<" : "<<x<<endl
using namespace std;
const int maxn = 100005;
int a[maxn],tmp[maxn];

ll merge(int l,int r){
    ll cnt = 0;
    if(l >= r){
        return cnt;
    }
    int mid = l + r >> 1;
    cnt += merge(l,mid);
    cnt += merge(mid+1,r);
    int k = 1;
    int i = l,j = mid + 1;
    while(i <= mid&&j <= r){
        if(a[i] <= a[j]){
            tmp[k++] = a[i++];
        }
        else{
            tmp[k++] = a[j++];
            cnt += mid - i + 1;
        }
    }
    while(i <= mid) tmp[k++] = a[i++];
    while(j<=r) tmp[k++] = a[j++];
    for(i = l , j = 1 ; i <= r ; i++ , j++ ){
        a[i] = tmp[j];
    }
    return cnt;
}
int main(){
    int n;in(n);
    for(int i = 1 ; i <= n ; i++ ) {
        in(a[i]);
    }
    ll res = merge(1,n);
    cout<<res<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值