noip 2015 pj 普及组 第四题 推销员 salesman
这道题的题目大意就是说一个人要到一段死胡同去推销,拜访第i个门户会消耗a[i]体力,走路也会消耗一些体力,第i个门户距离胡同口的距离是s[i],然后让你输出在不多余走路的情况下拜访1户(x==1),拜访2户(x==2)......拜访n(x==n)户分别最多要消耗多少体力。
初看这道题自己感觉没有任何头绪,于是反复读样例,发现这道题有一定的规律,当x==1时,答案就是最大的s[i]*2+a[i],这个值可以在输完s[i]的时候就判断出来。其中s[i]*2的原因是在死胡同里面走的时候,如果你要走到s[i]的深度且不走多余的路,那么从进去到出来你一定会走2*s[i]的路程,对吧?
那么此时我们已经有了x==1的答案,那么可以猜测我们是不是可以通过x==1来推出x==2,x==3乃至x==n的答案来呢?
首先,可以暴力枚举......不过一看数据规模,n<=100000,简直了,还是算了吧......
然后,继续反复读样例说明,每次x的值增加1的时候,一定会多走一个门户(其实这是一句废话),那么根据这条性质,我们需要多走的那个门户一定就是当前的未走的门户中耗费体力值最大的。ans[i]=ans[i-1]+max(门户消耗的体力),一定是这样的吧?那么,我们是不是可以每当x循环增加1以后,都找出当前还没走的门户消耗体力的最大值,也就是找出max(门户消耗的体力)......嗯,一定是这样......
可是每次这样找最大值就成了O(n^2)的复杂度,明显还是爆......那么该怎么办呢?显然,每次找最大值会进行大量的重复计算,所以我们可以使用优先队列,也就是建立一个大根堆,这样每次只用调用堆顶元素就可以找到当前未走的门户中耗费体力值最大的了。
既然使用优先队列,可以直接用STL里边的模板。
这道题貌似就解决了?NoNoNo!并没有这么简单!你看,我们的情况实际上有两种。一种情况是当前门户比之前最深的门户更深,此时我们需要考虑一下多走的路程所消耗的体力,还有一种情况是当前门户比之前最深的浅一些,这种情况比较简单,关键是第一种情况该如何处理。那么请放开你的脑洞,我们是不是可以建立两个堆,分别储存两种情况的最大值呢?
这就比较复杂了,先建立两个结构体堆,分别命名为lheap和rheap,分别存储较浅的门户和更深的门户,每一个节点分别储存的是
struct rec
{int data;//拜访当前户用的体力值 int l; //当前户与路口的距离 int sum;//拜访当前户的总体力值 (lheap存的是当前点的访问花费 rheap存的是单独访问当前点的花费) int xb;//数组下标
};
lheap的sum中由于不用考虑路程(总路程不会改变),所以光存当前门户的拜访花费即可;而rheap则要考虑路程的变化,为了方便计算,直接存储单独访问当前门户的花费,也就是s[i]*2+a[i]的值
既然考虑要判断当前的总路程,我们可以用一个l变量来记录
然后我们可以建立一个ans数组,存储x==1~n的答案,每次比较lheap和rheap的堆顶元素,将总消耗量大的加入到ans[i]中,就可以了
不过还有一个细节要处理,如果当前较大的堆顶元素是rheap中的,那我们还要刷新一下l的值,同时将rheap中深度小于新的l的值放进左堆中,代表它们的深度已经小于当前的最大门户深度了,这可以用一个while来实现
总时间复杂度为O(nlog(n)),不会TLE
于是我写了一个程序,放到洛谷上评测,结果就AC了
代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
int l;
int ans[100005];
struct rec
{int data;//拜访当前户用的体力值 int l; //当前户与路口的距离 int sum;//拜访当前户的总体力值 (lheap存的是当前点的访问话费 rheap存的是单独访问当前点的花费) int xb;//数组下标
};bool operator < (const rec &x,const rec &y)
{return x.sum < y.sum;
}
priority_queue<rec> lheap;
priority_queue<rec> rheap;
int n;
int s[100005];
int a[100005];
rec maxx;
int main()
{scanf("%d",&n);for(int i=1;i<=n;++i){scanf("%d",&s[i]);//读入路程 }for(int i=1;i<=n;++i){scanf("%d",&a[i]);//读入拜访花费 if(2*s[i]+a[i]>=maxx.sum)//找出一开始总花费最多的那一门户,并用maxx记录下来 {maxx.sum=2*s[i]+a[i];maxx.l=s[i];maxx.xb=i;maxx.data=a[i];}}printf("%d\n",maxx.sum);//先将x==1的情况输出 rec ls;for(int i=1;i<maxx.xb;++i)//建立左堆 {ls.data=a[i];ls.l=s[i];ls.xb=i;ls.sum=a[i];lheap.push(ls);}for(int i=maxx.xb+1;i<=n;++i)//建立右堆 {ls.data=a[i];ls.l=s[i];ls.xb=i;ls.sum=2*s[i]+a[i];rheap.push(ls);}int lx;l=maxx.l*2;//记录当前的最远距离 rec lsl,lsr;ans[1]=maxx.sum;for(int i=2;i<=n;i++){if(!rheap.empty() && !lheap.empty())//如果左右堆均不为空 {lsl=lheap.top();//分别记录下来左右堆的堆顶元素并进行比较 lsr=rheap.top();if(lsl.sum>lsr.sum-l){ans[i]=lsl.sum+ans[i-1];lheap.pop();}else{ans[i]=lsr.sum-l+ans[i-1];rheap.pop();l=2*lsr.l;while(rheap.top().l*2<=l && !rheap.empty()){lheap.push(rheap.top());rheap.pop();}}}else{if(lheap.empty()){lsr=rheap.top();ans[i]=lsr.sum-l+ans[i-1];rheap.pop();l=2*lsr.l;while(rheap.top().l*2<=l && !rheap.empty()){lheap.push(rheap.top());rheap.pop();}}else{lsl=lheap.top();ans[i]=lsl.sum+ans[i-1];lheap.pop();} } }for(int i=2;i<=n;i++){printf("%d\n",ans[i]);}return 0;
}
noip 2015 pj 普及组 第四题 推销员 salesman相关推荐
- NOIP2016 普及组第四题 魔法阵magic 题解
题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量. 大魔法师有m个魔法物品,编号分别为1,2,-,m.每个物品具有一个魔法值,我们用Xi表示编号为i的物品的魔法值.每 ...
- 洛谷 P1070 道路游戏(noip 2009 普及组 第四题)
题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 nn个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 nn个机器人工厂编 ...
- Noip2015普及组第四题 Salesman的解题报告
[题意分析] 咋一看,这一题可以用贪心做,但是,时间复杂度是O(n*n),只能过60%的数据. [贪心算法](超时,60分) #include<cstdio> #include<cs ...
- NOIP2016普及组第四题——魔法阵
题目描述 六十年一次的魔法战争就要开始了,大魔法师准备从附近的魔法场中汲取魔法能量. 大魔法师有m个魔法物品,编号分别为1,2,-,m.每个物品具有一个魔法值,我们用Xi表示编号为i的物品的魔法值.每 ...
- 子矩阵(NOIP2014 普及组第四题)
描述 给出如下定义: 子矩阵:从一个矩阵当中选取某些行和某些列交叉位置所组成的新矩阵(保持行与 列的相对顺序)被称为原矩阵的一个子矩阵. 例如,下面左图中选取第 2.4 行和第 2.4.5 列交叉位置 ...
- 2002普及组第四题过河卒
题目描述 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点有一个对方的马(如上图的C点),该马所在的点和所有跳跃一步可达的点称为对方马的控制点.例如 ...
- NOIP普及组历届真题(1997~2018)
供大家刷题. 先上快捷的查看方式:NOIP普及组历届真题 第二页 来自洛谷--一个很好的刷题网站 剩下是具体题目和难度以及是第几年的题. P1002 过河卒 NOIp普及组 2002 普及- P100 ...
- P1066 2^k进制数 NOIP 2006 提高组 第四题
洛谷蓝题(点击跳转) 提高组 第四题 题目描述 设r是个2^k 进制数,并满足以下条件: (1)r至少是个2位的2^k 进制数. (2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的 ...
- NOIP普及组第1题(1995-2018)
NOIP1995普及组复赛第1题 https://blog.csdn.net/secret_zz/article/details/76862335 https://blog.csdn.net/WDAJ ...
- 【codevs 1315】1315 摆花2012年NOIP全国联赛普及组(dp)
1315 摆花2012年NOIP全国联赛普及组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 小明的花店新开张,为 ...
最新文章
- html5游戏 虚拟主机,基于HTML5的云虚拟主机配置界面
- 2018年HBase生态社群画像 +最全资料汇总下载
- 坚持,这两个字非常重要!
- 二叉搜索树的第k个结点
- SDUT - 2604 Thrall’s Dream(tarjan+拓扑)
- kinect1+depthimage_to_laserscan
- Golang使用心得
- java检查文件的编码格式
- Python 语言创建 Abaqus inp 文件
- 来自陈沙克日志的收藏
- 2020牛客暑期多校训练营(第七场)J.Pointer Analysis
- 英语谚语大全(3267条)
- 2022哪些蓝牙耳机适合学生党?适合学生党的平价蓝牙耳机推荐
- Scons安装和使用
- python在线编程练习_有哪些在线编程练习网站?
- 实训1_获取产业数据并存储_预处理与简单分析
- 忽悠自由主义_所有教育工作者都应该知道的16种自由主义
- 思杰pvs服务器压力无法最大化,XXX学校桌面虚拟化方案重点.docx
- java i18n 国际化_springboot-i18n国际化
- 寒江独钓(1):内核数据类型和函数