题目描述
Description
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
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).
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
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=4911
解题思路
就是求逆序数,询问的是交换任意两个相邻的元素K次,使逆序数最大,最后输出最大的逆序数。
根据一个神奇的定理:如果逆序数大于0,那么必定存在1 <= i < n使得i和i + 1交换后逆序数减1。假设原逆序数为ans,这样的话,我们就可以得到答案是max(ans - k, 0)
。
下面给出了两种做法,一种做法就是归并排序法(算法导论学习1—分治法计算逆序数):
简单说下如何在归并的过程中,计算逆序数。假设,有一个序列array[p, mid, r]. 其中array[p…mid], array[mid + 1, …, r]已经分别从小到大排好序。下面我们将两个子序列进行归并。
假设当前的右边子序列(array[mid + 1, …, r])的当前待比较元素下表为right, 左边的为left, 当array[left] <= array[right]时, 这时候没有逆序发生(因为left的数比right的大);当array[left] > array[right]时,right指向的元素具有逆序数,个数为他之前的所有的数,即mid - left + 1。如此遍历下去,即可得到在归并中得到逆序数。
还有一种方法就是树状数组法:
由于这题的数据特别大,所以在使用树状数组的时候就需要将其离散化,然后再判断每一个元素前面有多少个元素就可以了。
AC代码(归并排序)
202MS/2352K/G++
1 |
|
AC代码(树状数组)
171MS/6280K/G++
1 |
|