题目链接: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 }
时间: 2024-10-07 13:34:20