http://acm.hdu.edu.cn/showproblem.php?pid=2838
题意 n个数的排列,每次可以互换相邻的元素,最终变成一个递增的序列,每次互换的代价为互换的两个数的和,求最小代价。
每次处理前i个,也就是顺序处理就是最小,假如第i个数为a[i],那么需要的代价为a[i]*c+sum(a[i]),c是a[i]前比a[i]大的数的个数,sum(a[i])是a[i]前比a[i]大的数的和,用树状数组,两个数组,一个存个数,一个存和
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=100010;
ll a[maxn];
ll b[maxn],c[maxn];//b是比a[i]小的个数,c是比a[i]小的数的和
int n;
ll lowbit(ll x)
{
return x&-x;
}
ll sum_b(ll x)
{
ll ret=0;
while(x>0)
{
ret+=b[x];
x-=lowbit(x);
}
return ret;
}
ll sum_c(ll x)
{
ll ret=0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
void update(int i,int j)
{
while(i<=n)
{
b[i]+=1;
c[i]+=j;
i+=lowbit(i);
}
}
int main()
{
while(scanf("%d",&n)!=-1)
{
long long ans=0,cnt=0;
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
update(a[i],a[i]);
cnt+=a[i];
ans+=a[i]*(i-sum_b(a[i]));
ans+=cnt-sum_c(a[i]);
}
printf("%lld\n",ans);
}
return 0;
}