Problem Description
bobo has a sequence a1,a2,…,an. He is allowed to swap twoadjacent numbers for no more than k times.
Find the minimum number of inversions after his swaps.
Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and ai>aj.
Find the minimum number of inversions after his swaps.
Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and ai>aj.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,k (1≤n≤105,0≤k≤109). The second line contains n integers a1,a2,…,an (0≤ai≤109).
The first line contains 2 integers n,k (1≤n≤105,0≤k≤109). The second line contains n integers a1,a2,…,an (0≤ai≤109).
Output
For each tests:
A single integer denotes the minimum number of inversions.
A single integer denotes the minimum number of inversions.
Sample Input
3 1 2 2 1 3 0 2 2 1
Sample Output
1 2
题目大意:给定 n 个数,和最多 k 次的调整,每次只能选择交换相邻的两个数,问最少能得到的逆序对的个数。
观察一下不难发现交换任意一对最多减少一个逆序对,不影响其他部分,那么思路及很简单了。求出逆序对的个数,减 k 即可,需要注意的是,k 大于原串逆序对个数时直接输出零就行。
求逆序对我是用树状数组写的,所以对数据离散化了一下,也可以用分治的思想直接求。
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int maxn = 1e5 + 5; ll t[maxn],sub[maxn],a[maxn]; bool vis[maxn]; int n; int lowbit(int x) { return x & -x; } ll query(int x) { ll sum = 0; while(x > 0) { sum += t[x]; x -= lowbit(x); } return sum; } void add(int x,int v) { while(x <= n) { t[x] += v; x += lowbit(x); } } int main() { int k; ll sum; while(scanf("%d %d",&n,&k) != EOF) { sum = 0; memset(t,0,sizeof(t)); memset(vis,false,sizeof(vis)); for(int i = 0;i < n; ++i) scanf("%d",&a[i]),sub[i] = a[i]; sort(sub,sub + n); int len = unique(sub,sub + n) - sub; for(int i = 0;i < n; ++i) { a[i] = lower_bound(sub,sub + len,a[i]) - sub + 1; } for(int i = 0;i < n; ++i) { sum += (query(n) - query(a[i])); add(a[i],1); } printf("%lld\n",k > sum ? 0 : sum - k); } return 0; }