逆序数(归并排序)

在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4。给出一个整数序列,求该序列的逆序数。

Input

第1行:N,N为序列的长度(n <= 50000)
第2 - N + 1行:序列中的元素(0 <= A[i] <= 10^9)

Output

输出逆序数

Input示例

4
2
4
3
1

Output示例

4

这题用归并排序做
#include <bits/stdc++.h>
using namespace std;

const int Maxn = 50010;
int A[Maxn];
int tmp[Maxn];
int cnt = 0;

void msort( int* A,int* tmp,int bg,int ed ){
    if( ed - bg > 1 ){
        int mid = bg + (ed-bg)/2;
        int x = bg;
        int y = mid;
        msort( A,tmp,bg,mid );
        msort( A,tmp,mid,ed );
        int index = bg;
        while( x < mid && y < ed ){
            if( A[x] > A[y] ){
                cnt += mid - x;//如果满足x < y and A[x] > A[y],即逆序,就加(mid-x),因为当前的A[x] > A[y],那么A[x]后面的所有数字都 > A[y],
                tmp[index++] = A[y++];
            }else{
                tmp[index++] = A[x++];
            }
        }
        while( x < mid ){
            tmp[index++] = A[x++];
        }
        while( y < ed ){
            tmp[index++] = A[y++];
        }
        for( int i = bg; i < ed; i++ ){
            A[i] = tmp[i];
        }
    }
}

int main(){
    int n;
    cin >> n;
    for( int i = 0; i < n; i++ ){
        cin >> A[i];
    }
    msort(A,tmp,0,n);
    cout << cnt << "\n";
}

以下是python代码

def sortandcount( alist ):
    n = len( alist )
    count = 0
    if n == 2 or n == 1:
        if n == 2:
            if alist[0] > alist[1]:
                alist = alist[::-1]
                count += 1
        return alist,count
    a,cnt1 = sortandcount( alist[:n/2] )
    b,cnt2 = sortandcount( alist[n/2:] )
    count += cnt1 + cnt2
    resList = [0]*n
    i = j = 0
    len1 = len( a )
    len2 = len( b )
    for k in range( n ):
        if i < len1 and j < len2:
            if a[i] < b[j]:
                resList[k] = a[i]
                i += 1
            else:
                resList[k] = b[j]
                count += len1 - i;
                j += 1
        elif i < len1:
            resList[k] = a[i]
            i += 1
        else:
            resList[k] = b[j]
            j += 1
    return resList ,count

def main():
    n = input()
    num = [ input() for i in range(n) ]
    i,c = sortandcount(num)
    print c

if __name__ == ‘__main__‘:
    main()
时间: 2024-10-17 19:36:20

逆序数(归并排序)的相关文章

nyist oj 117 求逆序数 (归并排序&amp;&amp;树状数组)

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组数(1<=T<=5) 每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000) 随后的一行共有N个整

1203: 逆序数 ( 归并排序 )

1203: 逆序数 Time Limit: 1 Sec Memory Limit: 128 MB Submit: 125 Solved: 26 [Submit][Status][Web Board] Description 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数不小于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 如2 4 3 1中,2 1,4 3,4 1,3 1是逆序,逆序数是4.给出一个整数序列,求该序列的逆序数. Input 多组测试数

51Nod 1019 逆序数 (归并排序)

1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 const int maxn = 50005; 6 int a[maxn]; 7 int res[maxn]; 8 int ans; 9 10 //归并排序 11 void merge(int l, int r){ 12 //cout<<l<<" "<<r<<endl; 13

归并排序——计算逆序数

归并排序——计算逆序数 归并排序用了分治的思想,时间复杂度o(N*logN)动态内存的运用可减小空间开销: 归并排序还可用于计算逆序数: 逆序数:序列中位置和大小相反的一对数字: 逆序数=冒泡排序中相邻两个数字交换的次数: int a[maxn],n; long long ans; //逆序数一般很大,用long long void compute_ans(int*a,int begin,int mid,int end) { int len_L=mid-begin+1; int len_R=en

poj 2299 逆序数

http://poj.org/problem?id=2299 坑:答案是long long 输出……!!!!! 题意是:求一个数组进行冒泡排序交换的次数 题解:求逆序数 题解Ⅰ: 归并排序求逆序数 归并排序求逆序数之前写过 1.归并排序是把两个有序的数组合并成为一个有序的数组,利用分治的思想就可以进行排序 逆序数可以利用这个思想求 求出第一个数组的逆序数,和第二个数组的逆序数,再将两个数组整体的逆序数求出来 f(x,y) = f(x,mid) + f(mid,y) + 之后数组的逆序数 #inc

归并排序_逆序数

归并排序求逆序数 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数.一个排列中所有逆序总数叫做这个排列的逆序数.也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序.一个排列中所有逆序总数叫做这个排列的逆序数. 1 #include<cstdio> 2 #in

求逆序数(归并排序)

求逆序数 时间限制:2000 ms  |  内存限制:65535 KB 难度:5 描述 在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序.一个排列中逆序的总数就称为这个排列的逆序数. 现在,给你一个N个元素的序列,请你判断出它的逆序数是多少. 比如 1 3 2 的逆序数就是1. 输入 第一行输入一个整数T表示测试数据的组数(1<=T<=5) 每组测试数据的每一行是一个整数N表示数列中共有N个元素(2〈=N〈=1000000) 随后的一行共有N个整

【上海交大oj】逆序数对(归并排序)

3021. 逆序数对 Description 给你一个数组,求该数组的逆序数 Input Format 输入文件第一行包含一个自然数N,N个数 接下来有N行,表示a[0],a[1]...a[n - 1] Output Format 输出文件仅有一行包含一个整数,表示该数组的逆序数 Sample Input 3 575085724 344369358 808884464 Sample Output 1==============================================所谓逆

poj 2299 Ultra-QuickSort 归并排序求逆序数对

题目链接: http://poj.org/problem?id=2299 题目描述: 给一个有n(n<=500000)个数的杂乱序列,问:如果用冒泡排序,把这n个数排成升序,需要交换几次? 解题思路: 根据冒泡排序的特点,我们可知,本题只需要统计每一个数的逆序数(如果有i<j,存在a[i] > a[j],则称a[i]与 a[j]为逆序数对),输出所有的数的逆序数的和用普通排序一定会超时,但是比较快的排序,像快排又无法统计 交换次数,这里就很好地体现了归并排序的优点.典型的利用归并排序求逆