题目链接:http://acm.hust.edu.cn/vjudge/problem/visitOriginUrl.action?id=52584

题意:

       先输入两个数n,k,n表示这组数的个数,k表示最多可以交换的次数,再输入一组数,交换相邻的数使它是从小到大排序,交换次数不能大于k,问,你交换到最后,还会有多少个倒置数。

      案例:

      input

      3 1

      2 2 1

      3 0

      2 2 1

      output

      1

      2

思路分析:

         在第一个案例中,最多交换一次,我要尽可能的使它从小到大排序,那么只能交换相邻的1,2,这样得到的是1,简单来说,就是在这些数中,在它前面却比它大的数的总和减去可以交换的数k就是所得答案,这让我想到归并排序,归并排序可以求出在它前面却比它大的数的总和。这样就可以得出答案。

         但是要注意一种情况,当需要交换的次数小于k呢?在这种情况输出0就行。

         注意:数的范围过大,要用long long型。

源代码如下:

 1 #include<iostream>
 2 #include<cstdio>
 3 #define MAX 100005
 4 using namespace std;
 5 int n;
 6 long long a[MAX],t[MAX],s,k;
 7 void merge_sort(long long *A,long long x,long long y,long long *T)
 8 {
 9     if(y-x>1)
10     {
11         long long m=x+(y-x)/2;
12         long long p=x,q=m,i=x;
13         merge_sort(A,x,m,T);
14         merge_sort(A,m,y,T);
15         while(p<m||q<y)
16         {
17             if(q>=y||(p<m&&A[p]<=A[q])) T[i++]=A[p++];
18             else {T[i++]=A[q++];s+=m-p;}     //需要交换次数
19         }
20         for(i=x;i<y;i++)A[i]=T[i];
21     }
22 }
23 int main()
24 {
25     while(scanf("%d%d",&n,&k)!=EOF)
26     {
27         s=0;
28         for(int i=0;i<n;i++)
29             scanf("%d",&a[i]);
30         merge_sort(a,0,n,t);
31         if(s>=k)
32             cout<<s-k<<endl;
33         else
34             cout<<"0"<<endl;
35     }
36     return 0;
37 }

 

posted on 2015-08-08 16:52  尘埃。  阅读(323)  评论(0编辑  收藏  举报