P2672 推销员 优先队列 + 贪心
题解:
我会说我想这道普及组题都想了好久么。。。。
不熟练的普及组选手.jpg
最后随便猜了一个结论居然是对的。。。
放结论:
假设x = i的最优决策为f[i], 那么f[i + 1]一定包括f[i].
也就是说f[i+1]一定可以由f[i]推出来。
所以f[i]一定是由f[i+1]中选定的所有点中去掉一个得来的。
即下一次选择一定是基于上一次选择的。。。
至于证明嘛。。。感性理解吧。
因为选哪户人家推销其实相互没太多联系。而且选i个推销肯定选满是最划得来的。。。。
大概是这么理解的吧。(反向理解可能更加好理解一点)
所以有了这个结论就很好解决了。
因为f[n]的最优决策肯定是n个点全选。
所以我们从这个已知的往前推。
于是我们来观察这n个点,到底删掉哪个减掉的疲劳值最小呢?
首先选中的这些点可以看做一个有序点集,位置由s[i]的大小所决定。
因此我们记last[x]为在x前面的第一个点的id, Next[x]为在x后面的第一个点的id。
于是有两种情况:
1,删去的点在末尾。
此时减掉的疲劳值为a[x] + 2 * (s[x] - s[last[x]])
2,删去的点在中间。
那么此时对走路的距离没有任何影响,因此我们只需要减a[x]即可。
值得注意的是,当末尾点k为a[i]最小的点时, 我们需要再取出次小的点来做比较,因为a[k]虽然最小,但由于要走很多路,所以a[k] + 2 * (s[k] - s[last[k]])并不一定小于a[i](i < k, 且i ∈ 点集),因此我们需要进一步比较再做取舍。
而k不是a[i]最小的点时,因为a[k]就已经大于a[i]了,所以减去的疲劳值肯定要大于a[i]了,因此直接删最小的点就可以了。
这里的最小和次小由于要支持插入,删除,查询,因此我们使用优先队列来实现。
为了方便查询元素的id,,,于是我又建了一个结构体、。
代码:
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define LL long long
#define getchar() *o++
#define AC 100100
char READ[], *o = READ;
int n;
int s[AC], a[AC], ans[AC], Next[AC], last[AC], r;
struct node{
int w, id;
}; struct cmp{
bool operator () (node a, node b)
{
return a.w > b.w;
}
}; priority_queue <node, vector<node>, cmp> q; inline int read()
{
int x = ; char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} void pre()
{
n = read();
for(R i = ; i <= n; i++) s[i] = read();
for(R i = ; i <= n; i++)
{
a[i] = read();
q.push((node){a[i], i});
ans[n] += a[i];
last[i] = i - ;
if(i != n) Next[i] = i + ;
}
ans[n] += s[n] * , r = n;
} void work()
{
int b = n - ;node x, now;
for(R i = b; i; i--)
{
x = q.top();
if(x.id == r)
{
q.pop();
now = q.top();
if(now.w < x.w + (s[x.id] - s[last[x.id]]) * )
{
q.pop();
Next[last[now.id]] = Next[now.id];
last[Next[now.id]] = last[now.id];
ans[i] = ans[i + ] - now.w;
q.push(x);
}
else//不然就删后者
{
Next[now.id] = ;
ans[i] = ans[i + ] - x.w - * (s[x.id] - s[last[x.id]]);
r = last[x.id];//移动末项
}
}
else//不然直接就删中间的了
{
q.pop();
Next[last[x.id]] = Next[x.id];
last[Next[x.id]] = last[x.id];
ans[i] = ans[i + ] - x.w;
}
}
for(R i = ; i <= n; i++) printf("%d\n", ans[i]);
} int main()
{
freopen("in.in", "r", stdin);
fread(READ, , , stdin);
pre();
work();
fclose(stdin);
return ;
}
P2672 推销员 优先队列 + 贪心的更多相关文章
- 洛谷P2672 推销员 题解 贪心
题目链接:https://www.luogu.org/problem/P2672 这道题目是贪心,贪心的思想是: 选择 \(m\) 户人家的最大疲劳值应该是以下两种方案中的较大值: 方案一:选择 \( ...
- 洛谷 P2672 推销员(贪心,模拟)
传送门 解题思路 第一种: 对于选i家,很显然,a值前i-1家的一定会选,所以只需要考虑最后一家的选法.要么是选择a值第i大的(就不管s了),要么选择剩下的中s最大的. 我们把每一家的情况(s和a)存 ...
- 洛谷 P2672 推销员 解题报告
P2672 推销员 题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第i家住户到入口的距离为 ...
- P2672 推销员(已经补锅)
P2672 推销员 下面讲正确的贪心 题解 考虑当推销员要推销 i 家客户时,他可以有两种选择: (1)选择前 i 家疲劳值 a 最大的客户,加上这些客户里最远的距离 (2)选择前 i-1 家疲劳值 ...
- 最高的奖励 - 优先队列&贪心 / 并查集
题目地址:http://www.51cpc.com/web/problem.php?id=1587 Summarize: 优先队列&贪心: 1. 按价值最高排序,价值相同则按完成时间越晚为先: ...
- POJ2431 优先队列+贪心 - biaobiao88
以下代码可对结构体数组中的元素进行排序,也差不多算是一个小小的模板了吧 #include<iostream> #include<algorithm> using namespa ...
- hdu3438 Buy and Resell(优先队列+贪心)
Buy and Resell Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- [luoguP2672] 推销员(贪心 + 树状数组 + 优先队列)
传送门 贪心...蒟蒻证明不会... 每一次找最大的即可,找出一次最大的,数列会分为左右两边,左边用stl优先队列维护,右边用树状数组维护.. (线段树超时了....) 代码 #include < ...
- luogu P2672 推销员 |贪心
题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第ii家住户到入口的距离为Si米.由于同一栋 ...
随机推荐
- Kubernetes网络方案的三大类别和六个场景
欢迎访问网易云社区,了解更多网易技术产品运营经验. 本文章根据网易云资深解决方案架构师 王必成在云原生用户大会上的分享整理. 今天我将分享个人对于网络方案的理解,以及网易云在交付 Kubernetes ...
- 追书神器API
由于自己喜欢看小说,有的时候不方便手机看的时候希望在电脑上面看,但很多网站有广告啊,于是封装了套手机版的追书神器API 目前只做了搜索 详情 书评 换源 正文 调用方式: //搜索小说 var sea ...
- 使用python中读取配置文件
最近在接触利用python来写测试框架,本人也是个刚接触python,所以是个小菜鸟,今天开始,一点点的记录学习中的积累,方便以后的学习以及回顾,也希望能帮助跟我一样的小菜鸟们一步步的成长起来.那么, ...
- Codeforces-A. Shortest path of the king(简单bfs记录路径)
A. Shortest path of the king time limit per test 1 second memory limit per test 64 megabytes input s ...
- Java学习 · 初识 IO流
IO流 1. 原理与概念 a) 流 i. 流动,流向 ii. 从一端移动到另一端 源头到目的地 iii. 抽象.动态概念,是一连 ...
- Github协作图想
首先 git pull 从远程拉下代码,并在本地与本地代码自动合并 在本地解决冲突后,可将本地代码进行远程推送 版本库的Repository中存储的是版本树状链,每一根链接线代表每一次的修改,每一个节 ...
- [Clr via C#读书笔记]Cp8方法
Cp8方法 构造器 作用就是初始化所有成员字段:.ctor:派生类和基类都有自己的构造函数.默认有一个无参数的构造函数,值字段初始化为0,引用字段初始化为null:可以有多个构造器: 值类型的初始化其 ...
- HADOOP docker(三):HDFS高可用实验
前言1.机器环境2.配置HA2.1 修改hdfs-site.xml2.2 设置core-site.xml3.配置手动HA3.1 关闭YARN.HDFS3.2 启动HDFS HA4.配置自动HA4. ...
- JavaScript筑基篇(三)->JS原型和原型链的理解
删除理由:很久以前写的,当时理解不够深入,这样描述反而看起来更复杂了.因此就删掉,免得误人子弟! 可以看看另一篇文章:[如何继承Date对象?由一道题彻底弄懂JS继承.](http://www.cnb ...
- Linux下误删文件恢复办法
恢复删除的文件 当误删除文件时,如果还有程序对此文件进行操作,那么可以通过lsof 命令恢复文件内容. 举例: 误删粗messages日志文件 [root@cdn ~]# cat /var/log/m ...