链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911
题意:给定一个序列和k,求在k次交换之后序列的逆序数,只能相邻两个数交换且只有左边的数大于右边时才能交换
代码如下
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<math.h> 5 #include<string.h> 6 #include<vector> 7 #include<queue> 8 #include<iterator> 9 #include<vector> 10 #include<set> 11 #define dinf 0x3f3f3f3f 12 typedef long long ll; 13 //const int Max=(1<<16)+10; 14 using namespace std; 15 #define SIZE 100000005 16 17 18 ll a[10000005],s[10000005],ans,k; 19 20 ll merge(int l1,int r1,int l2,int r2) 21 { 22 ans=0l; 23 int i,j,k; 24 for(i=l1;i<=r2;i++) 25 s[i]=a[i]; 26 27 i=l1;j=l2;k=l1; 28 while(i<=r1 && j<=r2) 29 { 30 if(s[i]<=s[j]) 31 a[k++]=s[i++]; 32 else 33 { 34 a[k++]=s[j++]; 35 ans+=(r1-i+1); 36 } 37 } 38 while(i<=r1) 39 a[k++]=s[i++]; 40 while(j<=r2) 41 a[k++]=s[j++]; 42 return ans; 43 } 44 45 ll merge_s(int l,int r) 46 { 47 ll ans=0l; 48 if(l<r) 49 { 50 int mid=(l+r)/2; 51 ans+=merge_s(l,mid); 52 ans+=merge_s(mid+1,r); 53 ans+=merge(l,mid,mid+1,r); 54 } 55 return ans; 56 } 57 58 59 int main() 60 { 61 int n; 62 while(~scanf("%d %lld",&n,&k)) 63 { 64 for(int i=1;i<=n;i++) 65 scanf("%lld",&a[i]); 66 ans=merge_s(1,n); 67 if(k>=ans) 68 printf("0\n"); 69 else 70 printf("%lld\n",ans-k); 71 } 72 return 0; 73 }