OJ4TH|Inverse number:Reborn

时间限制: 1000 ms 内存限制: 65536 kb

总通过人数: 234 总提交人数: 340

题目描述

输入一个正整数n,随后给出一个长度为n的整数序列a1,a2,a3...an。求给定序列的逆序数。

概念回顾:

逆序对:数列a[1],a[2],a[3]…中的任意两个数a[i],aj,如果a[i]>a[j],那么我们就说这两个数构成了一个逆序对。

逆序数:一个数列中逆序对的总数。

输入

多组测试数据。对于每组测试数据,给出序列长度n,和一个长度为n的序列a1,a2,a3...an

(0<n<=10^6,保证ai在int范围内)

输出

对于每组数据,输出该序列的逆序数。

输入样例

7 
3 5 4 8 2 6 9

输出样例

6

Hint

1、用n^2的算法是不行不行滴╮(╯_╰)╭
2、分治法

题解

OIers都知道这题的意思就是用归并排序求逆序对。

不过我WA了两次,最后发现ans不能用int来存……坑。

代码

#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;

int a[1000005],b[1000005];
long long ans;

void merge_sort(int l,int r)
{
    if (l==r) return;
    int mid=(l+r)/2;
    merge_sort(l,mid); merge_sort(mid+1,r);
    int i=l,j=mid+1,k=l;
    while (i<=mid && j<=r)
    {
        if (a[i]<=a[j]) b[k++]=a[i++];
        else 
        {
            b[k++]=a[j++];
            ans+=mid-i+1;
        }
    }
    while (i<=mid) b[k++]=a[i++];
    while (j<=r) b[k++]=a[j++];
    for (int t=l; t<=r; ++t) a[t]=b[t];
}

int main()
{
    int n;
    while (scanf("%d",&n)!=EOF)
    {
        ans=0;
        for (int i=1; i<=n; i++) scanf("%d",&a[i]);
        merge_sort(1,n);
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Shymuel/p/8573512.html