您的位置:首页 > 理论基础 > 数据结构算法

数据结构实验之排序五:归并求逆序数

2016-12-12 20:24 381 查看


数据结构实验之排序五:归并求逆序数

Time Limit: 40MS Memory Limit: 65536KB

Submit Statistic


Problem Description

对于数列a1,a2,a3…中的任意两个数ai,aj (i < j),如果ai > aj,那么我们就说这两个数构成了一个逆序对;在一个数列中逆序对的总数称之为逆序数,如数列 1 6 3 7 2 4 9中,(6,4)是一个逆序对,同样还有(3,2),(7,4),(6,2),(6,3)等等,你的任务是对给定的数列求出数列的逆序数。


Input

输入数据N(N <= 100000)表示数列中元素的个数,随后输入N个正整数,数字间以空格间隔。
 


Output

输出逆序数。


Example Input

10
10 9 8 7 6 5 4 3 2 1



Example Output

45



Hint


Author

归并排序是将数列a[l,h]分成两半a[l,mid]和a[mid+1,h]分别进行归并排序,然后再将这两半合并起来。

在合并的过程中(设l<=i<=mid,mid+1<=j<=h),当a[i]<=a[j]时,并不产生逆序数;当a[i]>a[j]时,在前半部分中比a[i]大的数都比a[j]大,将a[j]放在a[i]前面的话,逆序数要加上mid+1-i。因此,可以在归并排序中的合并过程中计算逆序数.

//C++提交超时
#include<iostream>
#include<stdio.h>
using namespace std;

int num[100004];//保存每一次归并完成后的序列
int a[100005];//初始的数组
long long int ccount;//记录逆序数个数

//归并子序列
void merge(int low1,int high1,int low2,int high2)//参数分别为第一个、第二个子序列的首尾下标
{
int count=0;//计数
int p1=low1;
int p2=low2;
while(p1<=high1&&p2<=high2)//注意边界是<=
{
if(a[p1]<=a[p2])
{
num[count++]=a[p1++];
}
else
{
num[count++]=a[p2++];
ccount+=high1+1-p1;//记录逆序数
}
}
if(p1<=high1)
{
for(int i=p1;i<=high1;i++)//注意边界是<=
{
num[count++]=a[i];
}
}
else
{
for(int i=p2;i<=high2;i++)//注意边界是<=
{
num[count++]=a[i];
}
}
for(int i=low1;i<=high2;i++)//把两个子序列重新合成一个序列
{
a[i]=num[i-low1];
}
}

//递归排序
void mergesort(int s,int t)
{
int low=s;
int high=t;
if(s<t)//这个地方边界是<
{
int mid=(low+high)/2;
mergesort(low,mid);
mergesort(mid+1,high);
merge(low,mid,mid+1,high);
}
}

int main()
{
ccount=0;
int n;
//cin>>n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
//cin>>a[i];
scanf("%d",&a[i]);
}
mergesort(0,n-1);
//cout<<ccount<<endl;
printf("%lld\n",ccount);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: