poj 2299

思路:

1、将原序列seq[]的下标按照seq[]的值升序排序存入res[]中。

2、假如我们知道res[j]的后面小于res[j]的数的个数x的话,那么res[j]需要交换的次数为j-res[j]+x;(自己推一下就知道)

3、如何求x呢?我们可以用树状数组sum[]来统计res[]从后往前处理过的数。

4、求和累加 j-res[j]+x; (jn-10)

 

#include<cstdio>

#include<iostream>

#include<algorithm>

using namespace std;

#define MAX 500010 

int seq[MAX],res[MAX];

__int64 sum[MAX];

bool com(int a,int b)

{

    return seq[a]<seq[b];

}

int lowbit(int i)

{

    return i & (-i);

}

int GetSum(int i)

{

    int s=0;

    while(i>0)

    {

        s+=sum[i];

        i-=lowbit(i);

    }

    return s;

}

int update(int i,int n)

{

    while(i<n)

    {

        sum[i]++;

        i+=lowbit(i);

    }

    return 0;

}



int main()

{

    int i,n;

    __int64 r;

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

    {

        memset(sum,0,sizeof(sum));

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

        {

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

            res[i]=i;

        }

        sort(res,res+n,com);

        r=0;

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

        {

            __int64 g=GetSum(res[i]);

            r+=i-res[i]+g;

            update(res[i]+1,n);

        }

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



    }

    return 0;

}

 

 

 

你可能感兴趣的:(poj)