~~~题面~~~

题解:

我会说我想这道普及组题都想了好久么。。。。

不熟练的普及组选手.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 推销员 优先队列 + 贪心的更多相关文章

  1. 洛谷P2672 推销员 题解 贪心

    题目链接:https://www.luogu.org/problem/P2672 这道题目是贪心,贪心的思想是: 选择 \(m\) 户人家的最大疲劳值应该是以下两种方案中的较大值: 方案一:选择 \( ...

  2. 洛谷 P2672 推销员(贪心,模拟)

    传送门 解题思路 第一种: 对于选i家,很显然,a值前i-1家的一定会选,所以只需要考虑最后一家的选法.要么是选择a值第i大的(就不管s了),要么选择剩下的中s最大的. 我们把每一家的情况(s和a)存 ...

  3. 洛谷 P2672 推销员 解题报告

    P2672 推销员 题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第i家住户到入口的距离为 ...

  4. P2672 推销员(已经补锅)

    P2672 推销员 下面讲正确的贪心 题解 考虑当推销员要推销 i 家客户时,他可以有两种选择: (1)选择前 i 家疲劳值 a 最大的客户,加上这些客户里最远的距离 (2)选择前 i-1 家疲劳值 ...

  5. 最高的奖励 - 优先队列&贪心 / 并查集

    题目地址:http://www.51cpc.com/web/problem.php?id=1587 Summarize: 优先队列&贪心: 1. 按价值最高排序,价值相同则按完成时间越晚为先: ...

  6. POJ2431 优先队列+贪心 - biaobiao88

    以下代码可对结构体数组中的元素进行排序,也差不多算是一个小小的模板了吧 #include<iostream> #include<algorithm> using namespa ...

  7. hdu3438 Buy and Resell(优先队列+贪心)

    Buy and Resell Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  8. [luoguP2672] 推销员(贪心 + 树状数组 + 优先队列)

    传送门 贪心...蒟蒻证明不会... 每一次找最大的即可,找出一次最大的,数列会分为左右两边,左边用stl优先队列维护,右边用树状数组维护.. (线段树超时了....) 代码 #include < ...

  9. luogu P2672 推销员 |贪心

    题目描述 阿明是一名推销员,他奉命到螺丝街推销他们公司的产品.螺丝街是一条死胡同,出口与入口是同一个,街道的一侧是围墙,另一侧是住户.螺丝街一共有N家住户,第ii家住户到入口的距离为Si米.由于同一栋 ...

随机推荐

  1. DSP5509的RTC实验-第3篇

    1. RTC实时时钟,不在过多介绍,本例程直接调用芯片支持库CSL的库函数,用起来比较简单 main() { CSL_init(); printf ("\nTESTING...\n" ...

  2. 四、新时间日期API

    一.使用 LocalDate .LocalTime .LocalDateTime LocalDate.LocalTime.LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-86 ...

  3. 「日常训练」Divisibility by Eight(Codeforces Round 306 Div.2 C)

    题意与分析 极简单的数论+思维题. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #de ...

  4. Windows运行机理——消息与消息队列

    Windows运行机理这系列文章都是来至于<零基础学Qt4编程>——吴迪,个人觉得写得很好,所以进行了搬运和个人加工 Windows程序设计时一种基于消息的时机驱动方式的设计模式,完全不同 ...

  5. Unity Lighting - Choosing a Lighting Technique 选择照明技术(一)

      Choosing a Lighting Technique 选择照明技术 https://unity3d.com/cn/learn/tutorials/topics/graphics/choosi ...

  6. Anyproxy抓包工具

    1.安装Nodejs和AnyProxy以及安装模拟器(移动端抓包工具) 第一步:nodejs下载地址:http://nodejs.cn/download/ 下载Windows版本,直接运行安装即可, ...

  7. Response对象及常用方法

    void addCookie(Cookie cookie)给客户端添加一个Cookie对象,以保存客户端的信息 void addDateHeader(String name,long value) 添 ...

  8. 【WXS全局对象】consloe

    consloe对象 方法: 原型:console.log( [String] ) 说明:用于在 console 窗口输出信息,一般用于程序调试使用示例: console.log支持arguments类 ...

  9. 深入理解java虚拟机学习笔记(一)

    第二章 Java内存区域与内存溢出异常 运行时数据区域 程序计数器(Program Counter Register) 程序计数器:当前线程所执行的字节码行号指示器.各条线程之间计数器互不影响,独立存 ...

  10. POJ 3046

    题目大意:蚂蚁牙黑,蚂蚁牙红:有A只蚂蚁,来自T个家族,分别记为ant[i]个.同一个家族的蚂蚁长得一样,但是不同家族的蚂蚁牙齿颜色不同.任取n只蚂蚁(S <= n <= B),求能组成几 ...