HDU 4911 Inversion - 疯狂的癫子 解题心得

原题:

Description

bobo has a sequence a 1,a 2,…,a n. 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 a i>a j.
 

Input

The input consists of several tests. For each tests: 

The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤ai≤10 9).
 

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
 
 
分析:
先用归并法求逆序数,再将逆序数减去k,结果为正   答案即这个
                   结果为负  答案就是0
 
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
__int64 a[100005], cnt, c[100005];
__int64 k;
void merg(int low, int mid, int high)
{
    int i = low, j = mid + 1;
    cnt = 0;
    while (i <= mid&&j <= high)
    {
        if (a[i]>a[j])
        {
            c[cnt++] = a[j++];
            k += mid - i + 1;
        }
        else
        {
            c[cnt++] = a[i++];
        }
    }
    while (i <= mid)
    {
        c[cnt++] = a[i++];
    }
    while (j <= high)
    {
        c[cnt++] = a[j++];
    }
    cnt = 0; i = low;
    while (i <= high)
    {
        a[i++] = c[cnt++];
    }
}
void merger(int low, int high)
{
    int mid;
    if (low<high)
    {
        mid = (low + high) / 2;
        merger(low, mid);
        merger(mid + 1, high);
        merg(low, mid, high);
    }
}
int main()
{
    int i, n, m;
    while (~scanf("%d%d", &n, &m))
    {
        k = 0;
        for (i = 0; i<n; i++)
        {
            scanf("%I64d", &a[i]);
        }
        merger(0, n - 1);
        if (k - m <= 0)
            printf("0\n");
        else
            printf("%I64d\n", k - m);
    }
    return 0;
}

 

posted @ 2015-08-07 20:32  Shawn_Ji  阅读(556)  评论(0编辑  收藏  举报