前言
- 归并排序
- 注意数值范围,res用long long
- 一次“操作”可以消除一个逆序对,那么排序过程中交换总次数就是逆序对个数
- 归并排序的过程用于求逆序对,Right部分被选中时,个数为mid-left+1
#include<iostream>
using namespace std;
int num[100010];
int tmp[100010];
long long res;
void merge(int left, int mid, int right) {
int i = left, j = mid+1, idx = 0; // 注意tmp永远从0开始
while (i <= mid && j <= right) {
if (num[i] > num[j]) {
tmp[idx++] = num[j++];
res += mid-i+1; // 最关键一步!
} else
tmp[idx++] = num[i++];
}
while (i <= mid) tmp[idx++] = num[i++];
while (j <= right) tmp[idx++] = num[j++];
}
void merge_sort(int left, int right) {
if (left >= right) return;
int mid = (left+right) / 2;
merge_sort(left, mid); // 左边排序
merge_sort(mid+1, right); // 右边排序
merge(left, mid, right); // 合
for (int i = left; i <= right; i++)
num[i] = tmp[i-left]; // 赋给num[], 注意i-left是因为tmp每次都从0开始
}
int main() {
ios::sync_with_stdio(false);
int n, k;
while (cin >> n >> k) {
for (int i = 0; i < n; i++)
cin >> num[i];
res = 0; // 归并排序要交换的总次数
merge_sort(0, n-1);
res <= k ? cout << 0 << endl : cout << res-k << endl;
}
}