题意:一个由n个非负整数组成的序列,问进行最多k次相邻交换后最少的逆序对数 (1 ≤ n ≤ 10^5, 0 ≤ k ≤ 10^9, 0 ≤ ai ≤ 10^9)。。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911
——>>每次只能交换相邻的两个数,每次交换,只改变这两个数的逆序,其他的数对于这两个数的逆序没有改变,所以,求出所有的逆序对,再减去k就是答案。
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int MAXN = 100000 + 10;int n, k;
int a[MAXN], b[MAXN];
long long C[MAXN];void Init()
{memset(C, 0, sizeof(C));
}void Read()
{for (int i = 0; i < n; ++i){scanf("%d", a + i);}
}int Lowbit(int x)
{return x & (-x);
}long long Sum(int x)
{long long nRet = 0;while (x > 0){nRet += C[x];x -= Lowbit(x);}return nRet;
}void Add(int x)
{while (x <= n){C[x]++;x += Lowbit(x);}
}void Solve()
{int nCnt = 0;int nId = 0;long long nReverse = 0;memcpy(b, a, sizeof(a));sort(b, b + n);nCnt = unique(b, b + n) - b;for (int i = n - 1; i >= 0; --i){nId = lower_bound(b, b + nCnt, a[i]) - b + 1;nReverse += Sum(nId - 1);Add(nId);}if (nReverse > k){nReverse -= k;}else{nReverse = 0;}printf("%I64d\n", nReverse);
}int main()
{while (scanf("%d%d", &n, &k) == 2){Init();Read();Solve();}return 0;
}