poj 2299 Ultra-QuickSort

来源:互联网 发布:刺客信条叛变优化补丁 编辑:程序博客网 时间:2024/06/07 07:22

在一个数列中,只能交换相邻的值,求排序该数列需要的最小的交换次数


归并排序,求出每个数的逆序数,(逆序数为该数后面比该数小的元素的个数)


9 1 0 5 4

9的逆序数为4,后面有4个比它小,同理1的逆序数为1,5的逆序数为1

将所有数的逆序数之后求出来,即为交换的最小步数


冒泡直接tle


采用归并排序求逆序数

#include <iostream>
#include <cstdio>
#include <cstring>

#define i64 long long

const int maxN = 500005;
const int inf = 1000000000;

int a[maxN];
int L[maxN];
int R[maxN];
i64 sum;

void merge(int s,int e)
{
    int mid = (s+e)>>1;
    int len1 = mid+1-s;
    int len2 = e-mid;
    for(int i = 0;i<len1;i++)
    {
    L[i] = a[s+i];
    }
    for(int i = 0;i<len2;i++)
    {
    R[i] = a[mid+i+1];
    }
    L[len1] = inf;
    R[len2] = inf;
    int j=0,k=0;
    for(int i = s;i<=e;i++)
    {
    if(L[j]<=R[k])
    {
        a[i] = L[j++];
        len1--;
    }
    else
    {
        a[i] = R[k++];
        sum += len1;//此时左边还剩下有len1个数,这些数都比R[k]小,所以R[k]的逆序数为len1
    }
    }
}

void mergesort(int s,int e)
{
    if(s<e)
    {
    int mid = (s+e)>>1;
    mergesort(s,mid);
    mergesort(mid+1,e);
    merge(s,e);
    }
}

int main()
{
    int n;
    while(scanf("%d",&n)&&n)
    {
    for(int i = 0;i<n;i++)
    {
        scanf("%d",&a[i]);
    }
    sum = 0;
    mergesort(0,n-1);
    printf("%lld\n",sum);
    }
}