Inversion
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1488 Accepted Submission(s): 606
Total Submission(s): 1488 Accepted Submission(s): 606
Problem Description
bobo has a sequence a1,a2,…,an. He is allowed to swap twoadjacent 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.
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).
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.
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
Source
2014 Multi-University Training Contest 5
题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=4911
题目大意 :给出n个数,每次可以交换相邻的两个数,最多交换k次,求交换后最小的逆序数是多少。
题目分析 :若逆序数大于0,则存在1 ≤ i < n,使得交换a[i]和a[i+1]后逆序数减1,所以最后的答案就是max((原数列逆序数对数 - k), 0)。利用归并排序求出原序列的逆序对数即可
题目链接 :http://acm.hdu.edu.cn/showproblem.php?pid=4911
题目大意 :给出n个数,每次可以交换相邻的两个数,最多交换k次,求交换后最小的逆序数是多少。
题目分析 :若逆序数大于0,则存在1 ≤ i < n,使得交换a[i]和a[i+1]后逆序数减1,所以最后的答案就是max((原数列逆序数对数 - k), 0)。利用归并排序求出原序列的逆序对数即可
#include <cstdio>
#define ll long long
const int MAX = 1e5 + 5;
int a[MAX];
ll num; //逆序对个数
//求逆序对个数模板
void mergg(int *arr,int low, int mid, int high)
{
int* b = new int[high + 1]; //b[] 复制 arr[]
for (int i = low;i <= high;++i)
b[i] = arr[i];
int i = low, j = mid + 1, k = low;
while (i <= mid && j <= high)
{
if (b[i] <= b[j])
arr[k++] = b[i++];
else
{
//发生逆序,此时由于a[i..mid]是已经有序了,
//那么a[i+1], a[i+2], ... a[mid]都是大于a[j]的,
//都可以和a[j]组成逆序对,因此number += mid - i + 1
arr[k++] = b[j++];
num += mid - i + 1;
}
}
while (i <= mid)
arr[k++] = b[i++]; //这两种情况只会发生一种
while (j <= high)
arr[k++] = b[j++];
delete []b;
}
void merge_sort(int *arr,int low,int high) //二路归并排序
{
if (low < high)
{
int mid = low + (high - low) / 2; //防溢出
merge_sort(arr, low, mid);
merge_sort(arr, mid + 1, high);
mergg(arr, low, mid, high);
}
}
int main()
{
int n, k;
while(scanf("%d%d",&n,&k) != EOF)
{
num = 0;
for(int i = 0; i < n; i++)
scanf("%d", &a[i]);
merge_sort(a, 0, n-1);
printf("%I64d\n", num - k > 0 ? num - k : 0);
}
}