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

试题描述
阿明是一名推销员,他奉命到螺丝街推销他们公司的产品。螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户。螺丝街一共有 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. php笔记(三)PHP类和对象之访问控制

    访问控制通过关键字public,protected和private来实现.被定义为公有的类成员可以在任何地方被访问.被定义为受保护的类成员则可以被其自身以及其子类和父类访问.被定义为私有的类成员则只能 ...

  2. 2015 QQ最新登录算法

    首先还是取得验证码,抓包可得:http://check.ptlogin2.qq.com/check?regmaster=&pt_tea=1&uin=2630366651&app ...

  3. ueditor1.4.3 在IE8下的 BUG

    ueditor1.4.3  .net 版 在IE8 下,多图片上传完成后,点击确认时报错,无法插入图片到编辑器中 原因是 ueditor.all.js 中的 24835 行 if (whitList[ ...

  4. php MYSQL 一条语句中COUNT出不同的条件

    SELECT DISTINCT c.uid, count( 1 ) AS zongji, count( if( task_type = 'mobile', true, NULL ) ) AS mobi ...

  5. 基础dp

    队友的建议,让我去学一学kuangbin的基础dp,在这里小小的整理总结一下吧. 首先我感觉自己还远远不够称为一个dp选手,一是这些题目还远不够,二是定义状态的经验不足.不过这些题目让我在一定程度上加 ...

  6. git中添加多个SSH公钥,以及不同系统之间的差别

    git学习已经也有一段时间了,基本的操作,口令会了一点点,但是还没有git团队开发的实践,这个有待加强~ git是在windows下面模拟Linux环境的,linux自带的ssh服务,可以通过该服务远 ...

  7. ios隐藏软键盘

    //判断是否为苹果 var isIPHONE = navigator.userAgent.toUpperCase().indexOf('IPHONE')!= -1; // 元素失去焦点隐藏iphone ...

  8. Atitit 版本管理----分支管理

    Atitit 版本管理----分支管理 版本管理系统"(Version Control System Branch/tag在一个功能选项中,在使用中很容易产生混淆. 分支(Branch)管理 ...

  9. 设计模式--装饰者设计模式(Decorator)

    装饰者模式又叫包装模式. 通过另一个对象来扩展自己的行为,在不破坏类的封装的情况下,实现松耦合,易扩展的效果.   抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口可以给这些对象动态地添加职责 ...

  10. CSU 1639 队长,我想进集训队!

    水题 #include<cstdio> int main() { int x1, x2, x3, u, h; int n; while (~scanf("%d", &a ...