Cow Sorting

hdoj 2838

题目大意:给出数,求排成正序的最少时间,每两个数交换的时间是 两个数的值的和。

解决:树状数组,只需求出 在这个数加入之前比这个数大的个数,然后更新,再求出这个数加入之前比这个数大的数的总和

总共的代价是:cnt*加入的数+比这个数大的数的和

#include <iostream>
#include <functional>
#include <algorithm>
using namespace std;
#define LL __int64
const int N=100000;
LL sum[N+5]; //第i个数前比数num[i]大的数的和 
LL cnt[N+5]; //第i个数前比数num[i]大的数的个数
inline int lowbit(int x)
{
    return x&(-x);
}

void update(LL t[],int p,int delta)
{
    for(int i=p;i>0;i-=lowbit(i))
       t[i]+=delta;
}
LL getsum(LL t[],int p)
{
    LL tot=0;
    for(int i=p;i<=N;i+=lowbit(i))
      tot+=t[i];
    return tot;  
}

int main()
{
       int n, t;
        scanf("%d",&n);
   
        LL ans=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&t);
           //注意这个tmp必须是LL长整型的
            LL tmp=getsum(cnt,t+1);
            update(cnt,t,1);
            //这个s必须是长整型的,就是这个地方错了好几次的。
            LL s=getsum(sum,t+1);
            update(sum,t,t);
            ans += tmp*t+s;
        }
        printf("%I64d\n",ans);

    system("pause");
    return 0;
} 

原文地址:https://www.cnblogs.com/hpustudent/p/2193206.html