Inversion
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1648 Accepted Submission(s): 458
Problem Description
bobo has a sequence a1,a2,…,an. He is allowed to swap two adjacent 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.
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).
Output
For each tests: 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 做了那么多次的多校,终于打破一题的神话了,做了两题,哈哈,写下题解,也算激励激励自己。 这次的1001题很水,做法也很多,可以用归并,树状数组,线段树做,不过树状数组和线段树需要离 散化数据,数据太大了。 题意: 给你一组数据,和k次操作,每次操作可以交换任意两个相邻的数,问在不超出k次的操作下, 可以得到的最小逆序对; 做法: 仔细想一下就可以知道其实你每次移动减少的逆序对数都为一,所以可以先直接求出原来数组的 逆序对,再减去k即可; 代码如下:/****************************************************** / /* /* * *********** * * * Auther: ZSGG * * * * * * Name: Inversion * * * * * *********** Algorithm: 数据结构 * * * */ /*******************************************************/ #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <queue> #include <vector> #include <cstdlib> #include <algorithm> #define ls u << 1 #define rs u << 1 | 1 #define lson l, mid, u << 1 #define rson mid + 1, r, u << 1 | 1 using namespace std; typedef long long ll; const int M = 1e5 + 5; ll sum[M << 2]; int a[M],b[M]; void build_tree(int l, int r, int u) { if(l == r) { sum[u] = 0; } else { int mid = (l + r) >> 1; build_tree(l, mid, ls); build_tree(mid + 1, r, rs); sum[u] = sum[ls] + sum[rs]; // 555555555这句话竟然忘记加了,太粗心了; } } void update(int pos, int l, int r, int u) { if(l == r) { sum[u]++; return ; } int mid = (l + r) >> 1; if(pos <= mid) update(pos, lson); else update(pos, rson); sum[u] = sum[ls] + sum[rs]; } ll add(int L, int R, int l, int r, int u) { if(L > R) return 0; if(L <= l && R >= r) { return sum[u]; } ll res = 0; int mid = (l + r) >> 1; if(L <= mid) res += add(L, R, lson); if(R > mid) res += add(L, R, rson); return res; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n,k; while(~scanf("%d %d",&n,&k)) { ll res = 0; for(int i = 0; i < n; i++) scanf("%d",a+i); copy(a, a + n, b); sort(b, b + n); int ans = unique(b, b + n) - b;//离散化 build_tree(1, ans, 1); for(int i = 0; i < n; i++) { int ua = lower_bound(b, b + ans, a[i]) - b + 1;//二分查找数的位置 // cout<<ua<<endl; res += add(ua + 1, ans, 1, ans, 1);//查找逆序对数 update(ua, 1, ans, 1); //更新 } res -= k; if(res <= 0) puts("0"); else printf("%I64d\n",res); } return 0; }