hdu2838

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;
}
    原文作者:B树
    原文地址: https://blog.csdn.net/aonaigayiximasi/article/details/51455495
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞