HDU2838 Cow Sorting 树状数组

来源:互联网 发布:c语言中的头文件是 编辑:程序博客网 时间:2024/06/14 09:25

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2838


题目大意:Sherlock有N(1≤N≤100,000)头牛一字排开,在晚上挤奶。每头奶牛都有一个唯一的“坏脾气”的值,它们的坏脾气的范围为1... 100,000。由于脾气暴躁的奶牛更容易损坏Sherlock的挤奶设备,福尔摩斯想给奶牛重新排序,使它们按坏脾气增加的顺序排列。在此过程中,任何两个奶牛的地方(相邻)可以互换。由于脾气暴躁的牛难以移动的,它需要福尔摩斯花费的时间为两头奶牛的坏脾气的总和,例如移动坏脾气为X,Y的两头奶牛,需要时间为X+Y。
请帮福尔摩斯计算出重新排序奶牛需要的最短的时间。


分析:该题求一个序列里面所有逆序对的数字和。对于序列里值为x的第i个元素,需要知道前i个元素里比x小的元素的个数以及它们的和,因此需要两个树状数组,一个用来记录比a小的元素的个数cnt,另一个记录它们的和sum,为了简化程序,可以用结构体实现。那么对于移动第i头牛所需时间为sum+cnt×x。



实现代码如下:

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int M=100001;struct node{    int cnt;    long long sum;}a[M];int n;int lowbit(int i){    return i&(-i);}void update(int i,int x,int cnt){    while(i<=n)    {        a[i].sum+=x;        a[i].cnt+=cnt;        i+=lowbit(i);    }}int query_cnt(int n){//返回n以前比n小的数的个数    int ans=0;    while(n>0)    {        ans+=a[n].cnt;        n-=lowbit(n);    }    return ans;}long long query_sum(int n){//返回n以前多有数的和    long long ans=0;    while(n>0)    {        ans+=a[n].sum;        n-=lowbit(n);    }    return ans;}int main(){    while(scanf("%d",&n)!=-1)    {        long long ans=0;        memset(a,0,sizeof(a));        for(int i=1;i<=n;i++)        {            int x;            scanf("%d",&x);            update(x,x,1);            long long k=i-query_cnt(x);            if(k!=0)            {                long long tmp=query_sum(n)-query_sum(x);                ans+=k*x+tmp;            }        }        printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击