HDU 2838 Cow Sorting(树状数组)

HDU 2838 Cow Sorting(树状数组)

     http://acm.hdu.edu.cn/showproblem.php?pid=2838
Problem Description
Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" level in the range 1...100,000. Since grumpy cows are more likely to damage Sherlock's milking equipment, Sherlock would like to reorder the cows in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes Sherlock a total of X + Y units of time to exchange two cows whose grumpiness levels are X and Y.

Please help Sherlock calculate the minimal time required to reorder the cows.

分析:

        首先每次只能交换相邻的两头牛,并且最后要求升序排列,所以最后整个序列的逆序是0,每次交换只可以消除1个逆序。(令a[i]的逆序是从1到i-1比它大的数的个数。)

        现在想问我们用插入排序的方式从左到右一个一个消除逆序的话,最后得到的时间和是最小的吗?是的。证明如下:

        对于每个原始的a[i],假设在它前面有x和y比a[i]大,所以a[i]的逆序是2,消除a[i]逆序的代价必须是x+y+2a[i],因为如果x或y不与a[i]交换,那么x或y就永远在a[i]前面,逆序不可能消除。所以要消除任意a[i]的逆序,以上代价都是必须的且是最小的

        现在用树状数组来求消除逆序的代价。要建两颗树状数组,其中树组1用来计算当前已经有多少个值比a[i]大已经出现了,即temp1(类似于上面例子的2=temp1),树组2用来计算当前所有比a[i]大的值之和是多少?即temp2(x+y=temp2)。

        从左到右依次扫描a[i],首先执行temp1=sum(1,MAXN)-sum(1,a[i]);   temp2=sum(2,MAXN)-sum(2,a[i]);则temp1*a[i]+temp2就是消除a[i]逆序的代价,所以ans+=temp1*a[i]+temp2;

        然后接着插入a[i],执行:

        add(1,a[i],1); add(2,a[i],a[i]);

        最终结果可能超出int,要用long long

AC代码:31ms

#include
#include
#include
using namespace std;
const int MAXN=100000+100;
long long c[3][MAXN];
int lowbit(int x)
{
    return x&(-x);
}
long long sum(int i,int x)
{
    long long res=0;
    while(x>0)
    {
        res +=c[i][x];
        x-=lowbit(x);
    }
    return res;
}
void add(int i,int x,long long v)
{
    while(x


你可能感兴趣的:(ACM--题解汇总,practice,again,数据结构--树状数组,need,to,review,★★)