您的位置:首页 > 其它

HDU 4911 Inversion【归并排序求逆序数】

2015-08-12 16:34 393 查看

Inversion

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 2725 Accepted Submission(s): 1008



[align=left]Problem Description[/align]
bobo has a sequence a1,a2,…,an. He is allowed to swap twoadjacent numbers for no more than k times.

Find the minimum number of inversions after his swaps.

Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and ai>aj.

[align=left]Input[/align]
The input consists of several tests. For each tests:

The first line contains 2 integers n,k (1≤n≤105,0≤k≤109). The second line contains n integers a1,a2,…,an (0≤ai≤109).

[align=left]Output[/align]
For each tests:

A single integer denotes the minimum number of inversions.

[align=left]Sample Input[/align]

3 1
2 2 1
3 0
2 2 1


[align=left]Sample Output[/align]

1
2


嗯,题目大意就是说,n和k,n代表数据个数,k代表数据相邻之间交换的次数限制。还是归并排序找到排到从小到大的最小次数然后减去k 就是最小的inversions(因为归并排序是稳定的,而sort不是稳定的)(这里我实验证明用malloc多次申请内存再释放是很费时间的,在主函数里申请一次就ok这里TLE了我几次,然后还是比直接申请一个数组要节省一点点时间的,节省了大概80ms)

#include <iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#define maxn 100000+10
using namespace std;
long long n,cnt,k,a[maxn],p[maxn];
void Merge(long long left,long long mid,long long right,long long *p)
{
long long n=mid,m=right;
long long i=left,j=mid+1;
long long num=0;
while(i<=n&&j<=m)
{
if(a[i]<=a[j])
p[num++]=a[i++];
else
{
p[num++]=a[j++];
cnt+=n-i+1;
}
}
while(i<=n)
p[num++]=a[i++];
while(j<=m)
p[num++]=a[j++];
for(int i=0;i<num;++i)
a[left+i]=p[i];
}
void mergesort(long long left,long long right,long long *p)
{

if(left<right)
{
long long mid=(left+right)/2;
mergesort(left,mid,p);
mergesort(mid+1,right,p);
Merge(left,mid,right,p);
}
}
int main()
{
while(cin>>n>>k)
{
for(int i=0;i<n;++i)
cin>>a[i];
cnt=0;
long long *p=(long long *)malloc(sizeof(long long)*n);
mergesort(0,n-1,p);
if(cnt<=k)
cout<<0<<endl;
else
cout<<cnt-k<<endl;
free(p);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: