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就可以了。
样例过了但不知道错在哪的话,就自己多写一些极限情况下的数据进行测试。
解题思路:按音调从低到高排成一列,这样对于每头牛来说只需考虑它前面的牛就可以了,对于牛 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; }
相关文章推荐
- C#数据结构之顺序表(SeqList)实例详解
- Lua教程(七):数据结构详解
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- C#数据结构之队列(Quene)实例详解
- C#数据结构揭秘一
- C#数据结构之单链表(LinkList)实例详解
- 数据结构之Treap详解
- 一个有趣的SQL命题 用一条语句切换BIT型的真假值
- 用C语言举例讲解数据结构中的算法复杂度结与顺序表
- C#数据结构之堆栈(Stack)实例详解
- C#数据结构之双向链表(DbLinkList)实例详解
- JavaScript数据结构和算法之图和图算法
- Java数据结构及算法实例:冒泡排序 Bubble Sort
- Java数据结构及算法实例:插入排序 Insertion Sort
- Java数据结构及算法实例:考拉兹猜想 Collatz Conjecture
- java数据结构之java实现栈
- java数据结构之实现双向链表的示例
- Java数据结构及算法实例:选择排序 Selection Sort
- Java数据结构及算法实例:朴素字符匹配 Brute Force
- Java数据结构及算法实例:汉诺塔问题 Hanoi