您的位置:首页 > 其它

HDU2838 Cow Sorting 树状数组

2015-10-10 21:25 162 查看
题目链接: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
.cnt;
n-=lowbit(n);
}
return ans;
}
long long query_sum(int n)
{//返回n以前多有数的和
long long ans=0;
while(n>0)
{
ans+=a
.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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: