nyoj 117 归并求逆序数

链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=117

花了一晚上和上午的时间终于调试出来了,一开始没有考虑到存在相等数字的情况~~

这里有必要对归并排序进行总结。分为分治三步法

1.划分问题:把序列分成元素个数尽量相等的两半

2.递归求解:把两半元素分别排序

3.合并问题:把两个有序表合并成一个

此题求逆序中的第二步就是统计i,j均在左边或者均在右边的逆序对个数,合并问题则是统计i在左边,但j在右边的逆序对个数。

这里采取的策略可以这样理解,合并过程中,对于右边的元素按照从小到大的序列排序出列时,每出一个,左边存在几个元素,这表示该元素相对于左边有几个逆序(这里不包括自身右边的元素)

AC代码:

#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
long long sum;
int a[1000008];
void Merge(int a[],int first,int mid,int last,int b[])
{
int i,j,k,m,t=0,s1;
i=first;
j=mid;
k=mid+1;
m=last;
s1=mid-first+1;
while(i<=j&&k<=m)
{
if(a[i]<=a[k])
b[t++]=a[i++];
else
{
sum=sum+s1-i+first;       //注意这里,i的值是相对于first的,所以要加上first
b[t++]=a[k++];
}
}
while(i<=j)
b[t++]=a[i++];
while(k<=m)
b[t++]=a[k++];
for(k=0;k<t;++k)        //利用b辅助数组进行排序
a[first+k]=b[k];
}
void Sort(int a[],int first,int last,int b[])
{
if(first<last)
{
int mid=(first+last)/2;
Sort(a,first,mid,b);
Sort(a,mid+1,last,b);
Merge(a,first,mid,last,b);
}
}
int main()
{
int test,n,i;
scanf("%d",&test);
while(test--)
{
sum=0;
memset(a,0,sizeof(a));
scanf("%d",&n);
for(i=0;i<n;++i)
scanf("%d",&a[i]);
int *p=new int[n+1];
Sort(a,0,n-1,p);
printf("%lld\n",sum);       //sum必须为long long类型
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值