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;
}

 

 

 

posted @ 2012-11-27 23:13  书山有路,学海无涯  阅读(149)  评论(0编辑  收藏  举报