归并排序找逆序数
2015-08-07 20:09
399 查看
题意:
bobo has a sequence a 1,a 2,…,a n. 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 a i>a j.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
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
分析:归并排序+贪心
这里有个k要注意,就是可以交换相邻数字的位置,使得逆序数最小,那么我们肯定是把最小的数字往前换,这样我们算逆序数就只要把原来的逆序数算出来再减去可以交换的次数就好了,当然如果算出来是负数我们就让它直接等于零吧!
代码:
bobo has a sequence a 1,a 2,…,a n. 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 a i>a j.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
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
分析:归并排序+贪心
这里有个k要注意,就是可以交换相邻数字的位置,使得逆序数最小,那么我们肯定是把最小的数字往前换,这样我们算逆序数就只要把原来的逆序数算出来再减去可以交换的次数就好了,当然如果算出来是负数我们就让它直接等于零吧!
代码:
#include<iostream> using namespace std; const int maxn =100000+5; const int Q = 50000 + 5; int arr[maxn]; int lef[Q], rig[Q]; long long ans; int lef_size; int rig_size; void Merger(int arr[], int L, int M, int R) { //归并整个数组 int i, j, k; lef_size = M - L; rig_size = R - M; for (i = L; i < M; i++) { lef[i - L] = arr[i]; //放在左边的数组 } for (i = M; i < R; i++) { rig[i - M] = arr[i]; //放在右边的数组 } i = 0; j = 0; k = L; while (i < lef_size&&j < rig_size) { if (lef[i] <= rig[j]) //左边数组小于右边数组 { arr[k] = lef[i]; //把左边数组的数放进整合数组中 i++; //左数组下标加加 k++; //整合数组下标加加 ans += j; //逆序数加加(相当于在找i与下一个i之间插进去的数字,只要有数字插队,就表示 //左边(也可以说前面)大于了右边的数字(后面),所以加J,可能有点不好理解, //自行脑补吧!) } else { arr[k] = rig[j]; j++; k++; } } while (i < lef_size) { //没有放完的左边的数 arr[k] = lef[i]; i++; k++; ans += j; } while (j < rig_size) { arr[k] = rig[j]; j++; k++; } } void Mergersort(int arr[], int L, int R) { if (L + 1<R) //归并排序 { int M = (L + R) / 2; Mergersort(arr, L, M); Mergersort(arr, M, R); Merger(arr, L, M, R); } } int main() { int n; long long k; while (cin >> n>>k) { ans = 0; for (int m = 0; m < n; m++) cin >> arr[m]; Mergersort(arr, 0, n); if (ans - k > 0) cout << ans - k << endl; else cout << "0" << endl; } return 0; }
相关文章推荐
- 用 VIPER 构建 iOS 应用架构(2)
- Java Concurrency in Practice中对象锁重入问题的理解
- 第一周作业
- 用 VIPER 构建 iOS 应用架构(2)
- 神经元模型
- HDU - 4825 Xor Sum 字典树 + 二进制匹配
- 152 Maximum Product Subarray
- UVA10494 If We Were a Child Again
- mysql高可用之mha
- struts2中的bean标签
- SearchView setFilterText 关闭Toast 解决 SearchView 输入搜索词时出现悬浮窗
- Odoo POS
- 无法更新运行时文件夹共享状态:在客户机操作系统内装载共享文件夹文件系统时出错--解决办法
- hdu 1025 Constructing Roads In JGShining's Kingdom(DP)
- pku Power Strings
- poj 2752 Seek the Name, Seek the Fame
- hdu 1063 Exponentiation(有小数的高精)
- Java — 程序设计基础(Core Java I)
- C++对象模型——指向Data Members的指针(Pointer to Data Members)(第三章)
- windows平台下的换行