POJ - Ultra-QuickSort

题目大意

给定N个数(没有相同的值),对N个数进行升序排序,每次只能交换相邻的两个数,问最少需要多少次交换才能够让N个数成为升序排列的

题解

就是逆序对问题,如果a[i]>a[j](i<j)则就是一个逆序对,此题可以用归并排序解决,也可以树状数组,不过我是当树状数组来练习的。此题数据有点大0 ≤ a[i] ≤ 999,999,999,所以需要把N个数进行离散化,因为我们对每个数的值并不感兴趣,只需要知道每个数的大小即可。

代码

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#define MAXN 500005

using namespace std;

typedef struct

{

    long id;

    long t;

} NODE;

NODE a[MAXN];

long long c[MAXN];

long f[MAXN];

long n;

long lowbit(long x)

{

    return x&-x;

}

long sum(long x)

{

    long ret=0;

    while(x>0)

    {

        ret+=c[x];

        x-=lowbit(x);

    }

    return ret;

}

void add(long x,long d)

{

    while(x<=n)

    {

        c[x]+=d;

        x+=lowbit(x);

    }

}

bool cmp(NODE x,NODE y)

{

    return  x.t<y.t;

}

int main(void)

{

    long i;

    long long ans;

    while(scanf("%ld",&n)==1&&n)

    {

        for(i=1; i<=n; i++)

        {

            scanf("%ld",&a[i].t);

            a[i].id=i;

        }

        sort(a+1,a+n+1,cmp);

        memset(c,0,sizeof(c));

        for(i=1; i<=n; i++)

            f[a[i].id]=i;

            ans=0;

        for(i=n; i>=1; i--)

        {

            add(f[i],1);

            ans+=sum(f[i]-1);

        }

        printf("%I64d\n",ans);

    }

    return 0;

}

你可能感兴趣的:(Quicksort)