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

你可能感兴趣的:(HDU 4911 归并排序题目解析)