1. 程式人生 > >HDU 4911 歸併排序題目解析

HDU 4911 歸併排序題目解析

上題目

Inversion Time Limit: 2000/1000 MS (Java/Others) Memory Limit:
131072/131072 K (Java/Others) Total Submission(s): 2924 Accepted
Submission(s): 1081

Problem 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 1

Sample 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;
}