Sort 归并排序求逆序对

Time limit per test: 4.0 seconds

Time limit all tests: 4.0 seconds

Memory limit: 256 megabytes

You want to process a sequence of  n  distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order.

Input

There are several test cases, please process till EOF.

For each test case, the first line contains integer  n   (1n105) . The second line contains  n  space-separated integers  a1,a2,,an   (1ai109) .

Output

For each test case, output the minimum times of swapping in one line.

Examples

input
2
1 2
output
0

题意: 求逆序对。

分析:

首先理解归并排序。 给你一个混乱的序列,先将它分半变成两个序列,分别对每个序列排序,然后合并两个序列。  合并的操作就是每次比较两个序列的最小值,然后将最小值放到新的序列中,并再原序列删除那个最小值。

具体操作就是不断二分,至到每个序列只包含一个元素,这样就可以默认当前元素已经排好序了,再进行合并即可。

那怎么求逆序对呢? 对于每个即将要合并两个序列,我们可以知道在两个序列的内部是不存在逆序对的(因为已经是排好序的)。所以逆序对只存在两个序列之间。举例来说

假设第一个序列为 3 4 5       第二个序列为 1  2

那么对与合并操作,肯定要先比较 3 和 1 的大小,然后将1放到新的序列中。 可以因为3比1大,所以这是一个逆序对,同样的,对于第一个序列中所有大于3的元素,每一个都可以和1构成逆序对,所以cnt每次要加所有大于等于3的元素的个数。

具体看代码。

#include<iostream>
#include<cstdio>
#include<string.h>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<queue>
#include<iomanip>
using namespace std;
const int INF = 0x3f3f3f3f;
const int NINF = 0xc0c0c0c0;
const int maxn = 100005;
long long cnt = 0;
void merge_sort(int *A,int *T,int beg,int en)
{
    if(en-beg>1){
        int mid = beg + (en-beg)/2;
        int s1 = beg,s2 = mid;
        int e1 = mid,e2 = en;
        int pos = beg;
        merge_sort(A,T,s1,e1);		//缩小问题规模
        merge_sort(A,T,s2,e2);
        while(s1<e1 && s2<e2){
            if(A[s1] > A[s2]){
                cnt += e1-s1;			//只需要加一个cnt,即可求出逆序对的个数。
                T[pos++] = A[s2++];
            }
            else T[pos++] = A[s1++];
        }
        while(s1 < e1){			//若出现一个序列为空,则将另一个序列的元素依次放入新的序列。
            T[pos++] = A[s1++];
        }
        while(s2 < e2){
            T[pos++] = A[s2++];
        }
        for(pos = beg;pos<en;pos++)		//将每次合并好的序列放入原始序列(保证规模更大时,两个序列都是有序的)
            A[pos] = T[pos];
    }
}
int main()
{
    int A[maxn];	//原始序列
    int T[maxn];	//辅助序列
    int n;
    while(cin >> n){
        memset(T,0,sizeof(T));
        for(int i=0;i<n;i++){
            cin >> A[i];
        }
        cnt = 0 ;
        merge_sort(A,T,0,n);
        cout << cnt << endl;
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
归并排序是一种经典的排序算法,它通过将待排序的序列递归地划分成较小的子序列,然后将这些子序列进行合并,最终得到一个有序的序列。在归并排序的过程中,可以通过统计逆序对的数量来评估序列的有序程度。 使用归并排序逆序对的基本思想是:在合并两个有序子序列的过程中,如果左子序列中的元素大于右子序列中的元素,则构成了一个逆序对。在合并过程中,统计逆序对的数量,并将两个子序列合并成一个有序序列。 具体步骤如下: 1. 将待排序序列不断二分,直到每个子序列只有一个元素。 2. 逐层合并相邻的子序列,并在合并过程中统计逆序对的数量。 3. 重复步骤2,直到所有子序列合并成一个有序序列。 以下是使用归并排序逆序对的示例代码: ```python def merge_sort(arr): if len(arr) <= 1: return arr, 0 mid = len(arr) // 2 left, count_left = merge_sort(arr[:mid]) right, count_right = merge_sort(arr[mid:]) merged, count_merge = merge(left, right) return merged, count_left + count_right + count_merge def merge(left, right): merged = [] count = 0 i, j = 0, 0 while i < len(left) and j < len(right): if left[i] <= right[j]: merged.append(left[i]) i += 1 else: merged.append(right[j]) j += 1 count += len(left) - i merged.extend(left[i:]) merged.extend(right[j:]) return merged, count ``` 使用上述代码,可以通过调用`merge_sort`函数来解给定序列的逆序对数量。函数返回排序后的序列以及逆序对的数量。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值