您的位置:首页 > 其它

归并排序找逆序数

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要注意,就是可以交换相邻数字的位置,使得逆序数最小,那么我们肯定是把最小的数字往前换,这样我们算逆序数就只要把原来的逆序数算出来再减去可以交换的次数就好了,当然如果算出来是负数我们就让它直接等于零吧!

代码:

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: