首页 > 代码库 > 多校第五场 归并排序

多校第五场 归并排序

HDU 4911 Inversion

考点:归并排序

思路:这题呀比赛的时候忘了知道可以用归并排序算出逆序数,但是忘了归并排序的实质了,然后不会做……

因为看到题上说是相邻的两个数才能交换的时候,感觉归并排序好像不是得要相邻的呀,然后就这样晕……刚才重新看了才发现,归并就是相邻的交换的,正好是用来求逆序数的,唉……真的是做这个归并排序比赛就来了……真好!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<limits>
#include<bitset>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define INF 510010
#define maxn 100010
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
ll sum;
void merge(ll A[], int p, int q, int r)
{
    int n1 = q - p + 1;
    int n2 = r - q;
    ll *L=new ll[n1 + 1];
    ll *R=new ll[n2 + 1];
    for(int i = 0; i < n1; i++)
        L[i] = A[p + i];
    for(int i = 0; i < n2; i++)
        R[i] = A[q + 1 + i];
    L[n1] = numeric_limits<ll>::max();
    R[n2] = numeric_limits<ll>::max();
    int i = 0, j = 0;
    for(int k = p; k <= r; k++)
    {
        if(L[i] <= R[j]) A[k] = L[i],i++;
        else A[k] = R[j],j++,sum += n1 - i;
    }
    delete []L;
    delete []R;
}
void mergesort(ll A[], int l, int r)
{
    if(l >= r)
        return ;
    int q = (l + r) / 2;
    mergesort(A, l, q);
    mergesort(A, q + 1, r);
    merge(A, l, q, r);
}
ll a[100005];
int main()
{
    //freopen("test.txt","r",stdin);
    int n,k,i;
    while(~scanf("%d%d",&n,&k))
    {
        sum=0;
        for(i=0; i<n; i++)
            scanf("%d",a+i);
        mergesort(a,0,n-1);
        if(sum>k) printf("%I64d\n",sum-k);
        else puts("0");
    }
    return 0;
}