HDU_1394_Minimum Inversion Number

给定一组数,然后依次的挪动该组数的元素共得到n种序列。求这n中序列中逆序数最少的个数。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<cmath>

#include<algorithm>

#include<string>

#include<queue>

using namespace std;

#define N 5005

int n,c[N]; 

int sum(int x)

{

    int ret=0;

    while(x)

    {

        ret+=c[x];

        x-=x&-x;

    }

    return ret;

}

void add(int x)

{

    while(x<=n)

    {

        c[x]++;

        x+=x&-x;

    }

}

int main()

{

    int a[N],i,j,k;

    while(~scanf("%d",&n))

    {

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

        int ans=0;

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

        {

            scanf("%d",&a[i]);

            a[i]++;//a[i]从0开始,而树状数组下标从1开始,所以自增1

            add(a[i]);

            ans+=(i-sum(a[i])); //求得的逆序对

        }

        int Min=ans; 

        /*从后往前看,把a[n]移到第一位,逆序对增加a[i]-1,逆序对减少n-a[i]*/

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

        {

            ans+=2*a[i]-1-n;

            Min=min(ans,Min);

        }

        printf("%d\n",Min);

    }

    return 0;

}

 

你可能感兴趣的:(version)