题目大意:

有很多的牛n(100,000),每个牛都有一个暴躁值,现在想把这些牛按照暴躁值从小到大排序,每次只能交换两头相邻的牛,交换他们付出的代价就是,两头牛暴躁值的和。现在问你把这些牛按照暴躁值从小到大排序至少需要付出多少代价。

分析:

有点像求哪个逆序数,但是这里要分析一个问题,需要调换的次数是一定的,那么,如何调换才能付出最小的的代价。
比较感性的想法就是,每次调换代价最小的,但是这个贪心策略确实是有一点牵强,我就不证明了,应该是不对的,而且每次查找最小的也是够费劲的。
想简单一点,能不能证明出来,付出的代价是一定的。假设:存在 a [ i ] > a [ j ] ( i < j ) 。那么,在若干次相邻元素调换的过程中,一定存在一次操作是,调换 a [ i ] 和 a [ j ] (这里的 i,j 已经不是原来的 i,j 了,但是, a [ i ] 和 a [ j ] 还是原来的值,只是现在他们的位置通过之前的若干次调换,变成了相邻的)。所以,每一个逆序数对就意味着这两个要进行一次调换,也就是要付出一次代价,所以付出的代价确实是一定的。
关于代码实现,用两个树状数组。tree [ i ] 数组表示比 i 小的数的总和,treenum [ i ]数组表示比 i 小的数的个数。然后如何找到比 i 大的,就是 tree [ maxn ] - tree [ i ],treenum [ maxn ] - treenum [ i ]。

代码:

#include<iostream>
#include<string.h>
#include<stdio.h>

using namespace std;

long long int tree[105000]={0};
long long int treenum[105000]={0};
int n;
long long int s=0;
int lowbit(int x)
{
    return x&(-x);
}

void add(int x)//tree[x]及以上都加x
{
    int t=x;
    while(x<=100000)
    {
        treenum[x]+=1;
        tree[x]+=t;
        x=x+lowbit(x);
    }
}

long long int sum(int x)
{
    long long int f=0;
    while(x>=1)
    {
        f+=tree[x];
        x=x-lowbit(x);
    }
    return f;
}

long long int sumnum(int x)
{
    long long int f=0;
    while(x>=1)
    {
        f+=treenum[x];
        x=x-lowbit(x);
    }
    return f;
}

int main()
{
    int x;
    cin>>n;
    memset(tree,0,sizeof(tree));
    memset(treenum,0,sizeof(treenum));
    s=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        //cout<<sum(100000)<<endl<<sum(x)<<endl;
        s=s+(sum(100000)-sum(x))+(sumnum(100000)-sumnum(x))*x;
        add(x);
    }
    cout<<s<<endl;
}