HDU 4911 Inversion

          http://acm.hdu.edu.cn/showproblem.php?pid=4911   归并排序求逆对数

                Inversion

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


Problem Description
bobo has a sequence a1,a2,…,an. 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 ai>aj.
 

 

Input
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).
 

 

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
题意:相邻的最多调换k次,使得逆对数最小,
思路,先求出整个序列的逆对数-k次就可,如果出现负数就输出为0.用归并排序求逆对数。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
__int64 a[100005],cnt,c[100005];
__int64 k;
void merg(int low, int mid, int high)
{
  int i=low, j=mid+1;
  cnt=0;
  while(i<=mid&&j<=high)
  {
    if(a[i]>a[j])
    {
      c[cnt++]=a[j++];
      k+=mid-i+1;
    }
    else
    {
      c[cnt++]=a[i++];
    }
  }
  while(i<=mid)
  {
    c[cnt++]=a[i++];
  }
  while(j<=high)
  {
    c[cnt++]=a[j++];
  }
  cnt=0;i=low;
  while(i<=high)
  {
    a[i++]=c[cnt++];
  }
}
void merger(int low, int high)
{
  int mid;
  if(low<high)
  {
    mid=(low+high)/2;
    merger(low,mid);
    merger(mid+1,high);
    merg(low,mid,high);
  }
}
int main()
{
  int i,n,m;
  while(~scanf("%d%d",&n,&m))
  {
           k=0;
    for(i=0; i<n; i++)
    {
      scanf("%I64d",&a[i]);
    }
       merger(0,n-1);
    if(k-m<=0)
       printf("0\n");
     else
    printf("%I64d\n",k-m);
  }
  return 0;
}

 

 
posted @ 2014-08-06 10:42  疯狂的癫子  阅读(390)  评论(1编辑  收藏  举报