您的位置:首页 > 理论基础 > 数据结构算法

poj1990

2016-05-05 11:33 405 查看
题意:有n头牛排成一列,每头牛都有它自己的声调 v 和坐标 x ,两头牛交流消耗的能量为 max(v1,v2)*这两头牛之间的距离,求令这n头牛两两交流共消耗的能量。

解题思路:按音调从低到高排成一列,这样对于每头牛来说只需考虑它前面的牛就可以了,对于牛 i,前面牛的坐标可能大于也可能小于这头牛 ,所以需要两个树状数组 ,一个存放坐标,一个存放数量,令 

   down_sum表示小于等于此头牛的坐标之和

   up_sum表示大于此头牛的坐标之和

   down_num表示坐标小于等于此头牛的数量之和

   up_sum表示坐标大于此头牛的数量之和;

 那么 rel+=cow[i].v * (down_num*cow[i].x -down_sum)  // 坐标小于此头牛的能量之和

          rel+=cow[i].v * (up_sum - up_num * cow[i].x)        // 坐标大于此头牛的能量之和

wa了好几次,原因是MAX开小了,若向上更新的话,MAX一定要大于20000*2;若用total记录总坐标之和的话,时间复杂度会降低,而且只需向下更新,MAX开到20000+1就可以了。

样例过了但不知道错在哪的话,就自己多写一些极限情况下的数据进行测试。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#define MAX 1<<16
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;

ll N;
P cow[MAX];
ll up_tree[MAX];
ll down_tree[MAX];
ll num[MAX];

ll sum(ll *tree,ll a){
ll ans=0;
while(a>0){
ans+=tree[a];
a-=a&-a;
}
return ans;
}

void add(ll *tree,ll n,ll x){ ///向上更新
while(n<=MAX-1){
tree
+=x;
n+=n&-n;
}
}

int main(){
//  freopen("A.txt","r",stdin);
cin>>N;
for(ll i=1;i<=N;i++)
cin>>cow[i].first>>cow[i].second;
sort(cow+1,cow+N+1);

ll down_sum=0,up_sum=0; ///初始化
ll down_num=0,up_num=0;
ll rel=0;
memset(num,0,sizeof(num));
memset(down_tree,0,sizeof(down_tree));

for(ll i=1;i<=N;i++){
add(down_tree,cow[i].second,cow[i].second);
down_sum=sum(down_tree,cow[i].second);///小于cow[i].second的坐标之和
up_sum=sum(down_tree,MAX-1)-down_sum;

add(num,cow[i].second,1);
down_num=sum(num,cow[i].second); ///坐标小于cow[i].second的数量之和
up_num=sum(num,MAX-1)-down_num;

rel+=cow[i].first*(down_num*cow[i].second-down_sum); ///左半部分消耗能量
rel+=cow[i].first*( up_sum - up_num*cow[i].second ); ///右半部分消耗能量
}
cout<<rel;
return 0;
}


   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  BIT 数据结构