http://bigbang.openjudge.cn
归并——求逆序对数量
首先,逆序对数量cnt应该定义为long long类型
另外,输入输出最好使用printf和scanf,因为速度比cin、cout更快;使用cin、cout在洛谷上能够通过,但是在bigbang上面就不能通过,明明bigbang的数据量更小(bigbang上面n<=350000,洛谷上n<=500000),说明bigbang对时间卡得更严格。
#include<iostream>
#include<cstdio>
using namespace std;
long long cnt=0,n;
int a[550005];//保存元素的数组
int c[550005];//移动元素的数组,用来暂存有序的数组
void Merge(int* a,int left,int mid,int right,int* c){//归并两个序列
if(a[mid]>a[mid+1]){//如果有逆序才需要移动
int l=left,r=mid+1,m=mid;
int k=left;//注意是从left开始放的! 此题为递归,排序的范围是left~right,不是0~right
while(l<=mid&&r<=right){
if(a[l]<=a[r]){//小 大 =》符合条件的序列 ,直接把小的移动到c数组即可
c[k++]=a[l++];
}
else { //大 小 => 不符合条件的序列 ,把小的移动到c数组,并且统计逆序对数量
cnt+=mid-l+1;//从l到mid的数都是a[r]的 逆序对
c[k++]=a[r++];
}
}
while(l<=mid){//剩下的元素都是正确的序列了
c[k++]=a[l++];
}
while(r<=right){
c[k++]=a[r++];
}
//c中现在是有序的了,全部复制到a中,(因为排序是在a数组中进行的)
for(int i=left;i<=right;i++){
a[i]=c[i];
}
}
}
void Merge_sort(int* a,int left,int right,int* c){
if(left<right){//归并排序
int mid=(left+right)/2;
Merge_sort(a,left,mid,c);//对前半部分排序
Merge_sort(a,mid+1,right,c);//对后半部分排序
Merge(a,left,mid,right,c);//将两部分合起来
}
}
int main()
{
scanf("%lld",&n);
for(int i=0;i<n;i++){
//cin>>a[i];//使用cin,cout很可能会超时
scanf("%d",&a[i]);
}
int len=n;
Merge_sort(a,0,len-1,c);
for(int i=0;i<n;i++){
printf("%d ",a[i]);
}
printf("\n%lld",cnt);
return 0;
}
一个图片,序列6 5 4 3 2进行归并排序的过程