离散数学:求排列的逆序数

问题描述

3 2 5 1 4 中,(3, 2), (3, 1), (2, 1), (5, 1), (5, 4)是其5个逆序。

输入

第一行是一个整数n,表示该排列有n个数(n <= 100000)。

第二行是n个不同的正整数,之间以空格隔开,表示该排列。

输出

输出该排列的逆序数。

样例输入

5

3 2 5 1 4

样例输出

5

限时一秒
思路:利用二分归并排序算法(分治)

答案来自网络:平台得分66.6666,三组测试数据,最后一组反馈超时

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n,a[100009],tmp[100009];
long sum;
void Merge_sort(int,int);
void Merge_nx(int,int,int);
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    Merge_sort(1,n);
    printf("%ld",sum);//输出逆序总数 
    return 0;
}
void Merge_sort(int l,int r)
{
    if(l<r)//要有判断 
    {
    int mid=(l+r)>>1;//** 
    Merge_sort(1,mid);//归并左边 
    Merge_sort(mid+1,r);//归并右边 
    Merge_nx(l,mid,r);//归并排序 
    }
}
void Merge_nx(int l,int m,int r)
{
    int z=l,y=m+1;
    int num=l;// num=l*** 
    while(z<=m&&y<=r)
    {
        if(a[z]<=a[y])
        {
            tmp[num++]=a[z++];
        }
        else
        {
            tmp[num++]=a[y++];
            sum+=(m-z+1);//逆序总数 
        }
    }
    while(z<=m){tmp[num++]=a[z++];}//将剩下的直接放入 
    while(y<=r){tmp[num++]=a[y++];}
    for(int i=l;i<=r;i++)//l---r
    a[i]=tmp[i];//将排好的数返回 
}

猜你喜欢

转载自blog.csdn.net/qq_32239767/article/details/80426435