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