HDU 4911 歸併排序題目解析
上題目
Inversion Time Limit: 2000/1000 MS (Java/Others) Memory Limit:
131072/131072 K (Java/Others) Total Submission(s): 2924 Accepted
Submission(s): 1081Problem 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< 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).Output For each tests:
A single integer denotes the minimum number of inversions.
Sample Input
3 1
2 2 1
3 0
2 2 1Sample Output
1
2
翻譯
鑑於本人弱菜的英語 翻譯一下題意
第一行給2個數 N K n表示下面一行數的個數 看錶示你能操作的步數
問在進行最多K步操作之後最少能有幾對逆序對
分析
首先說求逆序對
常見2種方法: 歸併 和 樹狀陣列 。 這裡先講歸併 (樹狀陣列不會啊)
然後分析最小問題
如何營造最小的情況?
每一步都不浪費 每一步減少一個逆序對
可以這麼想如果兩個數是逆序的 那麼夾雜在兩者中間的數也一定是逆序的 這和數列是否排好序無關
所以直接用歸併排序計算出逆序對的個數減去K即可
但是注意不會出現負值
下面貼程式碼
歸併排序的程式碼挺重要的 儘量多敲幾遍 多理解
下面程式碼中的遞迴歸併排序函式可以當作模板用
#include<stdio.h>
#include<string.h>
long long count = 0;
int a[100000 + 5];
int b[100000 + 5];
void Merge(int sourceArr[], int tempArr[], int startIndex, int midIndex, int endIndex)
{
int i = startIndex, j = midIndex + 1, k = startIndex;
while (i != midIndex + 1 && j != endIndex + 1)
{
if (sourceArr[i] >= sourceArr[j])
tempArr[k++] = sourceArr[i++];
else
{
tempArr[k++] = sourceArr[j++];
count += midIndex - i + 1;
}
}
while (i != midIndex + 1)
tempArr[k++] = sourceArr[i++];
while (j != endIndex + 1)
tempArr[k++] = sourceArr[j++];
for (i = startIndex; i <= endIndex; i++)
sourceArr[i] = tempArr[i];
}
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex)
{
int midIndex;
if (startIndex < endIndex)
{
midIndex = (startIndex + endIndex) / 2;
MergeSort(sourceArr, tempArr, startIndex, midIndex);
MergeSort(sourceArr, tempArr, midIndex + 1, endIndex);
Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
}
}
int main(void)
{
int t, i, k, min, n, k;
while (scanf_s("%d %d", &n, &k) != EOF)
{
count = 0;
memset(a, 0, sizeof(a));
for (i = 1; i <= n; i++)
scanf_s("%d", &a[i]);
MergeSort(a, b, 0, n - 1);
if(count >= k)
count -=k;
else
count = 0;
printf("%d\n", count);
}
return 0;
}