您的位置:首页 > 其它

[HDOJ4911]Inversion

2015-08-20 21:01 288 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911

Inversion

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2744 Accepted Submission(s): 1015


[align=left]Problem Description[/align]
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.

[align=left]Input[/align]
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).

[align=left]Output[/align]
For each tests:

A single integer denotes the minimum number of inversions.

[align=left]Sample Input[/align]

3 1
2 2 1
3 0
2 2 1

[align=left]Sample Output[/align]

1
2

  求交换k次以后所获得的数列的最小的逆序数。

  如果逆序数大于0,说明数列中有两个数可以交换,使得逆序数-1。所以所求交换k次所得数列最小逆序数的结果就是排序结束后交换次数-k,这个结果大于等于0。

代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long LL;
const int maxn = 100010;
int num[maxn];
int Right[maxn], Left[maxn];
LL ans;

void merge(int* num, int p, int q, int r) {
int n1, n2, i, j, k;
n1 = q - p + 1;
n2 = r - q;
for(i = 0; i < n1; i++) {
Left[i] = num[p+i];
}
for(i = 0; i < n2; i++) {
Right[i] = num[q+i+1];
}
Left[n1] = Right[n2] = 0x7FFFFFFF;
i = 0;
j = 0;
for(k = p; k <= r; k++) {
if(Left[i] <= Right[j]) {
num[k] = Left[i];
i++;
}
else {
num[k] = Right[j];
j++;
ans += (n1 - i);
}
}
}

void mergesort(int* num, int p, int r) {
int q;
if(p < r) {
q = (p + r) / 2;
mergesort(num, p, q);
mergesort(num, q+1, r);
merge(num, p, q, r);
}
}

int main() {
int n, k;
while(~scanf("%d %d", &n, &k)) {
ans = 0;
for(int i = 0; i < n; i++) {
scanf("%d", &num[i]);
}
mergesort(num, 0, n-1);
cout << ((ans-k) > LL(0) ? ans-k : 0) << endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: