求逆序对数目

背景

雷蒙德·巴比特把他弟弟查理逼疯了。最近,雷蒙德只扫了一眼,就数出246根牙签在瞬间撒了一地。他甚至会数扑克牌。查理也很想做这样酷的事情。他想在类似的任务中击败他的兄弟。

问题

以下是查理的想法。假设你有一个N个数的序列。这样做的目的是移动数字,使序列的最后是有序的。唯一允许的操作是交换两个相邻的数。让我们举个例子:

从2803开始......

所以这个数列(2 8 0 3)可以用9次交换相邻数来排序。然而,它甚至可以用三种这样的交换来排序:

......

问题是:对给定序列进行相邻数交换的最小次数是多少?由于查理没有雷蒙德那样的智力,他决定作弊。这就是你发挥作用的地方。他让你为他写一个计算机程序,用O(nlogn)来回答这个问题。放心吧,他会为此出个好价钱的。

Input formats:

第一行包含序列的长度N (1 <= N <= 1000);第二行包含序列的N个元素(每个元素都是[-1000000,1000000]中的整数)。这一行中的所有数字都用空格隔开。

The output format:

打印一行,其中包含对给定序列排序所必需的相邻数交换的最小次数。

输入样例:

在这里给出一组输入。例如:

6
-42 23 6 28 -100 65537

输出样例:

在这里给出相应的输出。例如:

5

代码:

#include<iostream>
using namespace std;
int num;
void merge(int a[], int b[], int l, int m, int r)
{
    int i=l, j=m+1, k=l;
    while((i<=m) && (j<=r)){
        if(a[i] <= a[j] ){               //!!!!如果左边部分一直小于右边部分,相当于直接把右边第一个接到左边最后一个,不存在逆序对,num=0
            b[k++] = a[i++];    //左右比较,把较小那个填到数组b
        }else{
            b[k++] = a[j++];
            num += m-i+1;   //
        }
    }
    if(i>m){  //左边部分先于右边部分填完到数组b,把右边剩下的按原顺序填入数组b的空位
        for(int q=j; q<=r; q++){
            b[k++] = a[q];
        }
    }else{   //右边部分先于左边填完
        for(int q=i; q<=m; q++){
            b[k++]=a[q];
        }
    }
    for (int q = l; q <= r; q++)     // 中间是分成很多小步的,每次合并后都要复制回a数组
        a[q] = b[q];
}
void mergesort(int a[],int b[], int l, int r){
    if(r>l){          //至少有2个元素
        int i=(r+l)/2;
        //把数组左右拆成一个个
        mergesort(a, b, l, i);
        mergesort(a, b, i+1, r);
        merge(a, b, l, i, r); //合并到数组b
    }
}
int main()
{
    num=0;
    int n;
    cin >> n;
    int a[n], b[n];
    for(int i=0; i<n; i++)
        cin >> a[i];
    mergesort(a, b, 0, n); //r是指下标
    cout << num << endl;

}

// https://blog.csdn.net/weixin_45689999/article/details/110659992
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值