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

Inversion

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2725    Accepted Submission(s): 1008


Problem Description
bobo has a sequence a 1,a 2,…,a n. He is allowed to swap two adjacent 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 a i>a j.
 


 

Input
The input consists of several tests. For each tests:

The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
 


 

Output
For each tests:

A single integer denotes the minimum number of inversions.
 


 

Sample Input
  
  
3 1 2 2 1 3 0 2 2 1
 


 

Sample Output
  
  
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;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值