您的位置:首页 > 其它

poj 2299 逆序数 归并排序

2012-04-14 00:54 267 查看
陷阱啊!一开始我用冒泡排序(Bubble Sort)来统计。。晕,TLE。each case 50w.而一趟冒泡排序需要进行的是n-1,n-2,……,2,1,0的和次比较。即n*(n-1)/2次。总的时间复杂度为O(n^2).肯定是吃不消的。

于是,可以用归并排序来求它的逆序数,逆序即为它总共需要变换的次数。这样时间复杂度是nlog2n,而空间复杂度2n。 利用归并求逆序关键是对子序列s1和s2在归并时(s1,s2已经排好序),若s1[i]>s2[j](逆序状况),则逆序数加上s1.length-i,因为s1中i后面的数字对于s2[j]都是逆序的。参考:http://www.slyar.com/blog/poj-2299-c.html

#include <iostream>
#include <fstream>

using namespace std;
#define MAX 500005
int a[MAX],t[MAX];
__int64 cnt;

void Merge(int l,int mid,int r)
{
int i=l,j=mid+1,k=0;
while(i<=mid && j<=r)
{
if(a[i]>a[j])
{
t[k++]=a[j++];
cnt+=mid-i+1;
}
else
{
t[k++]=a[i++];
}

}

while(i<=mid) t[k++]=a[i++];
while(j<=r) t[k++]=a[j++];

//将归并完成的结果复制到原数组中
for(i=0; i<k; i++)
{
a[l+i]=t[i];
}
}

void MergeSort(int l,int r)
{
int mid=(l+r)/2;
if(l<r)
{
MergeSort(l,mid);
MergeSort(mid+1,r);
Merge(l,mid,r);
}
}

int main(){
int n,i;
freopen("acm.txt","r",stdin);
while( scanf("%d",&n)!=EOF && n)
{
for(i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
cnt=0;
MergeSort(0,n-1);
printf("%I64d\n",cnt);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: