题意:
给出一个数列,你要对这个数列的数字进行k次交换操作,使得交换之后的数列逆序对虽少。
思路:
求原数列的逆序对,再和k比就行了。求逆序对要用归并排序,因为树状数组开不下。
代码:
#include<cstdio>
#include<cstring>
#include<climits>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<sstream>
using namespace std;
long long _count;
int _left[2500003], _right[2500003];
void merge(int* a, int p, int q, int r)
{
int i, j, k, n1, n2;
n1 = q-p+1;
n2 = r-q;
for (i=0; i<n1; i++)
{
_left[i] = a[p+i];
}
for (i=0; i<n2; i++)
{
_right[i] = a[q+i+1];
}
_left[n1] = _right[n2] = 0x7fffffff;
i = j = 0;
for (k=p; k<=r; k++)
{
if (_left[i] <= _right[j])
{
a[k] = _left[i];
i++;
}
else
{
a[k] = _right[j];
j++;
_count += n1-i; /**此步骤是在归并排序法中加的一句,用来计数求逆序数的数目**/
}
}
return;
}
void mergesort(int* a, int p, int r)
{
int q;
if (p < r)
{
q = (p+r)/2;
mergesort(a, p, q);
mergesort(a, q+1, r);
merge(a, p, q, r);
}
return ;
}
int a[1000005];
int main()
{
int n,m;
int cas=1;
while(EOF != scanf("%d %d",&n, &m) ) {
_count=0;
for(int i = 0; i < n; i++) {
scanf("%d",&a[i]);
}
mergesort(a,0,n-1);
int ans;
_count-=m;
int flag=0;
for(int i=1;i<n;i++)
{
if(a[i]==a[i-1])
{
flag=1;
break;
}
}
if(_count<0)
{
_count=-_count;
if(_count%2==0)
ans=0;
else
if(flag)
ans=0;
else
ans=1;
}
else
ans=_count;
printf("Case #%d: %d\n",cas++,ans);
}
return 0;
}