好久没有写博客了,今天再写一篇。还是先看题:

试题描述
阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有 N 家住户,第 i 家住户到入口的距离为 Si 米。由于同一栋房子里可以有多家住户,所以可能有多家住户与入口的距离相等。阿明会从入口进入,依次向螺丝街的 X 家住户推销产品,然后再原路走出去。阿明每走 1 米就会积累 1 点疲劳值,向第 i 家住户推销产品会积累 Ai 点疲劳值。阿明是工作狂,他想知道,对于不同的 X,在不走多余的路的前提下,他最多可以积累多少点疲劳值。
输入
第一行有一个正整数 N,表示街住户数量,接下来一行有 N 个正整数,其中第 i 个整数 Si 表示第 i 家住户到入口距离保证 S1<=S2<=S3....<10 的 8 次方。接下来一行有 N 个整数,其中第 i 个整数 Ai 表示向第 i 个住户推销产品会积累疲劳值。保证 Ai<=10 的 3 次方。
输出
输出 N 行,每行一个正整数,其中第 i 行整数表示当 x=i,阿明积累的疲劳值。
输入示例
5
1 2 3 4 5
1 2 3 4 5
输出示例
15
19
22
24
25
其他说明
数据范围:1<= N <= 1000000。

针对每一个X,我在考场当时想能不能用贪心,每一次都选取当前那一个疲劳值最大的房子,但不知怎么了,认为不行,觉得应该用DP做,然后就当场懵逼了。现在想何尝不可以呢?证明很简单,只要用反证法即可。注意,题目中所说不走多余路的意思就是推销x的房子的时候必须一口气走完,不能绕来绕去,这样就更能说明了这样的贪心策略是可以的。本题为去年普及组最后一题,当时没做出来,现在就秒杀了,感觉自己有很大进步。

贪心策略想好了,下面就开始实现,如何选取当前那一个疲劳值最大的房子呢?对于一个没来过的房子(偏向右端),价值就是s[i]*2+a[i],这里指的是第一个,接下来就不一样了,每一次接下来选择的都是阿明走过最远房子的左端或右端中价值最大的房子。对于左端,因为不能走多余的路,所以价值就是a[i],右端呢,需要加上往返的距离,所以价值就是a[i]+(s[i]-now)*2,其中now指的就是阿明走过最远房子的位置,然后取一个最大值即可。如何快速找呢?很容易就能想到可以用一个最大堆来实现,就用STL里的priority_queue实现了,优先队列要声明两个,一个维护now左端的房子,另一个维护now右端的房子。注意开始时now=0;

想这么多就差不多可以开始写了,首先我先无脑写了一个结构体node,里面包含着四种信息(编号,a[i],s[i],价值),然后就把结构体读入了,但是到后来才知道:价值是会变的,在读入中盲目就读入价值是不行的……之后终于写完了,提交到oj上,结果时间超限,多交了几次,有一回999ms卡过了,我就意识到应该是读入的问题,于是就把scanf改成了read,然后就AC了。

下面是代码:

 #include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=;
int n,flag[maxn],ans,s[maxn],a[maxn],now;
struct node{
int s,val,num;
bool operator < (const node &b)const //重载运算符,目的是帮助优先队列排序
{
if(val!=b.val)return val<b.val;
return s<b.s;
}
};
node MAX(node a,node b){return a<b ? b :a;}
int read()
{
int x = , f = ; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -; c = getchar(); }
while(isdigit(c)){ x = x * + c - ''; c = getchar(); }
return x * f;
}
int main()
{
priority_queue <node> Q1,Q2;
n=read();
for(int i=;i<=n;i++)s[i]=read();
for(int i=;i<=n;i++)
{
a[i]=read();
Q2.push((node){s[i],a[i]+s[i]*,i});//由于初始位置是now,所以把所有都加入Q2,表示在右端
}
for(int i=;i<=n;i++)
{
node t1=(node){,,},t2=(node){,,};
if(Q2.size())
{
t1=Q2.top();Q2.pop();
while(t1.s<=now && Q2.size())t1=Q2.top(),Q2.pop();//把Q2中位于now左边的都删了
t1.val-=*now;
}
if(Q1.size())t2=Q1.top(),Q1.pop();
node t0=MAX(t1,t2);
if(t0.num==t2.num && t1.num)t1.val+=*now,Q2.push(t1);//注意在搁回Q2时,不要忘记将点权在加回2*now
else if(t0.num==t1.num)Q1.push(t2);//选取t0的操作是选取now左端和右端的点权最大值,在选取之后务必要把那个没有被选上的房子搁回队列中,要不就无视那房子了
flag[t0.num]=;
ans+=t0.val;
printf("%d\n",ans);
if(t0.s>now)
{
now=t0.s;
for(int j=;j<=t0.num;j++)//将位于now左边的全部加入Q2
if(!flag[j])
Q1.push((node){s[j],a[j],j});
}
}
return ;
}

调了很久才叫真正AC。

有几处小细节,是我在研读他人代码时发现的,我自己编的数据是这样的:

5

1 2 3 4 5

10 10 10 20 2

以及它的对称:

5

1 2 3 4 5

2 20 10 10 10

就是因为这两组数据卡爆了多少人,其中包括幸京睿,汪梁森,还有王子健。(然而李琦煜和吕紫剑的程序能完美解决这个问题)问题主要是出在第48,49行代码上,具体意思请看旁边注释。由此可见,小细节还是十分坑爹的,关于如何解决这些问题的话,还是要多做题吧。

在这里我来吐槽一下NOIP普及组给的测试数据究竟有多水,本人在之前有N多个bug的前提下仍旧AC了!!

NOIP2015普及组第四题推销员的更多相关文章

  1. 洛谷 P1070 道路游戏(noip 2009 普及组 第四题)

    题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 nn个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 nn个机器人工厂编 ...

  2. NOIP2015普及组总结

    NOIP2015普及组总结 这次考试总体感觉不错,不过觉得时间有点紧,在最后30分钟才打完. 第一题(金币coin):大大的W!爆搜O(N),一分钟打完: 第二题(扫雷游戏mine):同上: 第三题( ...

  3. [NOIP2015 普及组] 扫雷游戏

    [NOIP2015 普及组] 扫雷游戏 难度:入门 题目描述 扫雷游戏是一款十分经典的单机小游戏.在nn行mm列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开 ...

  4. NOIP2005普及组第4题 循环

    NOIP2005普及组第4题 循环 时间限制: 1 Sec  内存限制: 128 MB提交: 27  解决: 6[提交][状态][讨论版][命题人:外部导入] 题目描述 乐乐是一个聪明而又勤奋好学的孩 ...

  5. NOIP2005普及组第3题 采药 (背包问题)

    NOIP2005普及组第3题 采药 时间限制: 1 Sec  内存限制: 128 MB提交: 50  解决: 23[提交][状态][讨论版][命题人:外部导入] 题目描述 辰辰是个天资聪颖的孩子,他的 ...

  6. NOIP2008普及组第3题 传球游戏

    NOIP2008普及组第3题 传球游戏 时间限制: 1 Sec  内存限制: 128 MB提交: 29  解决: 16[提交][状态][讨论版][命题人:外部导入] 题目描述 上体育课的时候,小蛮的老 ...

  7. NOIP2004普及组第3题 FBI树

    /* 1106: NOIP2004普及组第3题 FBI树 时间限制: 1 Sec 内存限制: 128 MB 提交: 10 解决: 9 [提交] [状态] [讨论版] [命题人:外部导入] 题目描述 我 ...

  8. 普及C组第四题(8.9)

    2298. [noip普及组2T4]异或 (File IO): input:gcdxor.in output:gcdxor.out 题目描述 SarvaTathagata是个神仙,一天他在研究数论时, ...

  9. 洛谷【P2669】NOIP2015普及组 T1金币

    我对模拟的理解:http://www.cnblogs.com/AKMer/p/9064018.html 题目传送门:https://www.luogu.org/problemnew/show/P266 ...

随机推荐

  1. 【Time系列三】简单的计时器(秒表)

    之前在 "for与while的洪荒之力" 中介绍到计时器,不过那样弄感觉好麻烦啊, 碰巧昨天学Java的时候,讲到求余可以用来求时间 ! for与while链接: http://w ...

  2. centos php nginx 添加到service

    1. nginx A. # vi /etc/init.d/nginx B. #!/bin/sh # Comments to support chkconfig on RedHat Linux # ch ...

  3. js获取计算的样式(非行间样式)

    function getStyle(obj, attr){ if(obj.currentStyle){ style = obj.currentStyle[attr]; //兼容IE8以下 }else{ ...

  4. rune is alias of int32

    I think chendesheng's quote gets at the root cause best: Go uses a lot of signed values, not just fo ...

  5. 二十五、oracle pl/sql进阶--控制结构(分支,循环,控制)

    一.pl/sql的进阶--控制结构在任何计算机语言(c,java,pascal)都有各种控制语句(条件语句,循环结构,顺序控制结构...),在pl/sql中也存在这样的控制结构.在本部分学习完成后,希 ...

  6. 安装Postgresql踩过的坑

    PG安装相关的 1  系统语言的设置 PG的安装,和系统的locale设置有一定的关系,需要设置,如在.profile或.bashrc中 也可以运行下面的命令: dpkg-reconfigure lo ...

  7. HDU 5861 Road

    首先要计算出每一条路最早开始的那一天,然后最晚结束的那一天. 这些天之间这条边都必须$open$,然后就变成一个线段树区间$+val$的问题了,最后询问一个每个点的$val$是多少. 注意:数据中有$ ...

  8. JEMETER 录制

    两种方式: 第一种:badboy工具录制,导入jemeter脚本,导入jemeter.目测支持IE 第二种:代理服务器的方式 1.

  9. [JS思路]运动框架思路

    匀速运动的思路一: 1.先清除动画,再加载动画 2.方向dir有正值和负值,可以通过 目标值 > 当前值  往右移动,即正数 目标值 < 当前值  往右移动,即负数 来进行判断:dir = ...

  10. 说说SACC2016第八届架构师大会

    每年这方面的会议很多,不知不觉已经连续举办八年了.一届比一届办的有质量,规模越大.今年也如约而至.2016-10-27在北京万达索菲特酒店.4000多人规模,云集各领域顶尖架构师,运维,云计算,技术专 ...