囧。。水题。。。但是刚开始的时候居然没有读懂题目,题目就那么短啊你妹。。。
大意是给你一个长度为n的数列,给你k次机会任意调换相邻两个数的位置,然后求最小逆序数。
刚开始没有注意到数据范围是10^9,对线段树求逆序数的原理又不是太了解,然后一开始就用线段树做,果断wa了,RE了好久。。。
后来用归并做的。原谅我的渣。
感受:求逆序数就几种方法,一是线段树,二是用归并排序,三就是土法了。。。注意题目的数据范围,不然会用错方法。
上代码。
#include <stdio.h>
#define ll __int64
#define maxn 100001
ll left[maxn], right[maxn];
ll count;
void merge(ll* a, ll p, ll q, ll r)
{
ll 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(ll* a, ll p, ll r)
{
ll q;
if (p < r)
{
q = (p+r)/2;
mergesort(a, p, q);
mergesort(a, q+1, r);
merge(a, p, q, r);
}
return ;
}
int main()
{
ll n, t, a[maxn];
int i;
while (scanf("%I64d%I64d", &n,&t)!=EOF)
{
count = 0;
for (i=0; i<n; i++)
{
scanf("%I64d", &a[i]);
}
mergesort(a, 0, n-1);
count-=t;
if(count<0) count=0;
printf("%I64d\n", count);
}
}