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米.由于同一栋 ...
随机推荐
- VINS(四)初始化与相机IMU外参标定
和单目纯视觉的初始化只需要获取R,t和feature的深度不同,VIO的初始化话通常需要标定出所有的关键参数,包括速度,重力方向,feature深度,以及相机IMU外参$R_{c}^{b}$和$p_{ ...
- 创龙DSP6748学习之RS485收发
1. 先看下原理图,第一个问题,RS485其实就是使用的串口USART1,同时485的输出脚之间接120欧姆的电阻. 遇到个问题,为什么有两个使能引脚?还有RS485_A和RS485_B为什么分别接上 ...
- 拼接index
import MySQLdb import sys db = MySQLdb.connect(host="127.0.0.1", # your host, usually loca ...
- selenium(Java)WebDriverWait等待机制
//标题是不是“百度一下,你就知道” 18 new WebDriverWait(driver,5).until(ExpectedConditions.titleIs("百度一下,你就知道&q ...
- C++11 type_traits 之is_same源码分析
请看源码: template<typename _Tp, _Tp __v> struct integral_constant { static const _Tp value = __v; ...
- 【template、import、include】微信小程序:模板(template)、引用(import、include)说明
模板(template): 定义模板 <template name="[String]"> <!-- 模板代码 --> <view> <t ...
- 实现Bidirectional LSTM Classifier----深度学习RNN
双向循环神经网络(Bidirectional Recurrent Neural Networks,Bi-RNN),Schuster.Paliwal,1997年首次提出,和LSTM同年.Bi-RNN,增 ...
- LeetCode 144 ——二叉树的前序遍历
1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 将当前节点的数值加入到 data 中 递归得到其左子树的数据向量 temp,将 te ...
- dice2win
触发交易 转0个 https://etherscan.io/tx/0x784e80167353a886183106cbe3bd15e614cafdb5d6885ccd101177aa0f937a36 ...
- svn服务器 备份,迁移,部署方案
这次做业务迁移,要从一个云厂商迁移到某云厂商,之前每天到全备svn排到用场了,需要搭建一个全新到svn服务并要做迁移,并实现我们开发机到时时代码同步 一.svn备份有很多种,优劣都不同,百度可查,我采 ...