题面传送门

题意:

有 \(n\) 个展销会,每个展销会给出它的时间 \(t_i\),举办展销会的位置 \(l_i\),和参加这个展销会你能得到的收益 \(m_i\)。

你现在在位置 \(s\),你可以花 \(u\) 的代价从 \(i\) 走到 \(i-1\),或是花 \(d\) 的代价从 \(i\) 走到 \(i+1\)。

你只能先参加时间靠前的展销会,再参加时间靠后的展销会。

问从 \(s\) 出发并回到 \(s\) 能够获得的最大收益。

\(1 \leq n,t_i \leq 5 \times 10^5\),\(1 \leq l_i \leq 5 \times 10^5+1\),可能存在相同的 \(t_i\)。

这是一道 dp 题。

先考虑一个弱化版本的问题,假设没有 \(t_i\) 相同。

不难想到将这 \(n\) 个展销会按 \(t_i\) 从小到大排个序。

然后设 \(dp_i\) 表示参加前 \(i\) 个展销会,当前在第 \(i\) 个展销会的最大收益。

枚举上一个参加的展销会,于是我们就有 \(dp_i=\max\{dp_j-cost(j,i)\}+m_i\),其中 \(cost(j,i)\) 表示从第 \(j\) 个展销会所在的位置到达第 \(i\) 个展销会所在的位置的代价。

我们进一步对 \(cost(j,i)\) 进行展开,就有

\(dp_i=\max\{dp_j-(l_j-l_i)\times u\}+m_i\quad(l_j\geq l_i)\)

\(dp_i=\max\{dp_j-(l_i-l_j)\times d\}+m_i\quad(l_j\lt l_i)\)

拿第一个柿子举例,将 \(dp\) 柿子拆成与 \(i\) 有关的和与 \(j\) 有关的两部分,也就有

\(dp_j-(l_j-l_i)\times u=dp_j-l_j\times u+l_i\times u=(dp_j-l_j\times u)+l_i\times u\)

用树状数组维护 \(dp_j-l_j\times u\) 的最大值就可以在 \(\mathcal O(\log n)\) 的时间内求出 \(dp_i\)


但加上 \(t_i\) 可能相同的条件怎么办呢?

在举办时间相同的展销会当中,我们肯定是从左往右依次经过某些展销会,或是从右到左依次经过某些展销会,不走回头路。

于是我们可以把这 \(t_i\) 相同的展销会按 \(l_i\) 从小到大排个序。(显然这 \(t_i\) 相同的展销会的下标能够组成一个区间)

先求出从举办时间小于 \(t_i\) 的展销会到达 \(i\) 的最小代价 \(x_i\)。

然后设 \(dpl_i\) 表示以 \(i\) 结尾的一条从左至右的路径的最小代价。

\(dpr_i\) 表示以 \(i\) 结尾的一条从右至左的路径的最小代价。

以 \(dpl_i\) 为例,要么从从举办时间小于 \(t_i\) 的展销会到达展销会 \(i\),也就是 \(x_i\),要么从展销会 \(i-1\) 到底 \(i\),也就是 \(dp_{i-1}-(l_i-l_{i-1})\times d+m_i\),两者取一个 \(\max\) 即可。

最后 \(dp_i=\max(dpl_i,dpr_i)\)。

别忘了最后要回到位置 \(s\)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=500000+5;
const int MAXD=500001+5;
void chkmin(ll &x,ll y){(x>y)?(x=y):0;}
void chkmax(ll &x,ll y){(x<y)?(x=y):0;}
int n,s;ll u,d;
struct fair{
int t;ll l,m;
friend bool operator <(fair x,fair y){
if(x.t!=y.t) return x.t<y.t;
return x.l<y.l;
}
} a[MAXN];
struct fenwick_tree{
ll t[MAXD];
fenwick_tree(){memset(t,128,sizeof(t));}
void add(int x,ll v){for(int i=x;i<MAXD;i+=(i&(-i))) chkmax(t[i],v);}
ll query(int x){ll ret=-1e18;for(int i=x;i;i-=(i&(-i))) chkmax(ret,t[i]);return ret;}
} t1,t2;
ll dp[MAXN],dpd[MAXN],dpu[MAXN];
int main(){
scanf("%d%lld%lld%d",&n,&u,&d,&s);
t1.add(s,s*d);t2.add(MAXD-s+1,-s*u);
for(int i=1;i<=n;i++) scanf("%d%lld%lld",&a[i].t,&a[i].l,&a[i].m);
sort(a+1,a+n+1);memset(dp,128,sizeof(dp));
int l=1,r=1;
while(l<=n){
r=l;while(r<=n&&a[r].t==a[l].t) r++;r--;
// printf("%d %d\n",l,r);
for(int i=l;i<=r;i++){
dp[i]=max(dp[i],t1.query(a[i].l)-a[i].l*d);
dp[i]=max(dp[i],t2.query(MAXD-a[i].l-1)+a[i].l*u);
dp[i]+=a[i].m;
dpd[i]=dpu[i]=dp[i];
}
for(int i=l+1;i<=r;i++) dpd[i]=max(dpd[i],dpd[i-1]-(a[i].l-a[i-1].l)*d+a[i].m);
for(int i=r-1;i>=l;i--) dpu[i]=max(dpu[i],dpu[i+1]-(a[i+1].l-a[i].l)*u+a[i].m);
for(int i=l;i<=r;i++) dp[i]=max(dpd[i],dpu[i]);
for(int i=l;i<=r;i++) t1.add(a[i].l,dp[i]+a[i].l*d);
for(int i=l;i<=r;i++) t2.add(MAXD-a[i].l,dp[i]-a[i].l*u);
l=r+1;
}
// for(int i=1;i<=n;i++) printf("%lld\n",dp[i]);
ll ans=0;
for(int i=1;i<=n;i++) ans=max(ans,dp[i]-((a[i].l>s)?(a[i].l-s)*u:(s-a[i].l)*d));
printf("%lld\n",ans);
return 0;
}
/*
dp[i]=max{dp[j]+l[j]*d-l[i]*d}(l[j]<=l[i])
dp[i]=max{dp[j]-l[j]*u+l[i]*u}(l[j]>l[i])
*/

洛谷 P5902 [IOI2009]salesman(dp)的更多相关文章

  1. 洛谷P1108 低价购买[DP | LIS方案数]

    题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...

  2. NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp

    原文链接https://www.cnblogs.com/zhouzhendong/p/9261079.html 题目传送门 - 洛谷P3959 题目传送门 - Vijos P2032 题意 给定一个 ...

  3. 洛谷P1244 青蛙过河 DP/思路

    又是一道奇奇怪怪的DP(其实是思路题). 原文戳>>https://www.luogu.org/problem/show?pid=1244<< 这题的意思给的挺模糊,需要一定的 ...

  4. 洛谷P3928 Sequence2(dp,线段树)

    题目链接: 洛谷 题目大意在描述底下有.此处不赘述. 明显是个类似于LIS的dp. 令 $dp[i][j]$ 表示: $j=1$ 时表示已经处理了 $i$ 个数,上一个选的数来自序列 $A[0]$ 的 ...

  5. 洛谷P1140 相似基因 (DP)

    洛谷P1140 相似基因 题目背景 大家都知道,基因可以看作一个碱基对序列.它包含了44种核苷酸,简记作A,C,G,TA,C,G,T.生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物. ...

  6. 洛谷P2224 [HNOI2001] 产品加工 [DP补完计划,背包]

    题目传送门 产品加工 题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时 ...

  7. 洛谷1417 烹调方案 dp 贪心

    洛谷 1417 dp 传送门 挺有趣的一道dp题目,看上去接近于0/1背包,但是考虑到取每个点时间不同会对最后结果产生影响,因此需要进行预处理 对于物品x和物品y,当时间为p时,先加x后加y的收益为 ...

  8. 洛谷1387 二维dp 不是特别简略的题解 智商题

    洛谷1387 dp题目,刚开始写的时候使用了前缀和加搜索,复杂度大概在O(n ^ 3)级别,感觉这么写还是比较对得起普及/提高-的难度的..后来看了题解区各位大神的题解,开始一脸mb,之后备受启发. ...

  9. 洛谷 P2657 (数位DP)

    ### 洛谷 P2657 题目链接 ### 题目大意:给你一个数的范围 [A,B] ,问你这段区间内,有几个数满足如下条件: 1.两个相邻数位上的数的差值至少为 2 . 2.不包含前导零. 很简单的数 ...

随机推荐

  1. python jinja2初见

    吸取了长城杯的教训,学习python-web迫在眉睫. 正常难度的python_template_injection,由于现在没学面向对象,理解原理比较困难,所以先使用简单版复现:并附上正常版的常用p ...

  2. 学了ES6,还不会Promise的链式调用?🧐

    前言 本文主要讲解promise的链式调用的方法及其最终方案 应用场景 假如开发有个需求是先要请求到第一个数据,然后根据第一个数据再去请求第二个数据,再根据第二个数据去请求第三个数据...一直到最后得 ...

  3. UltraSoft - Beta - 设计与计划

    在DDL Killer的Alpha发布版本一周后,我们积累了一定的用户数量和用户反馈,同时也着手准备Beta阶段的继续开发,在正式开始迭代前,先对我们的Beta阶段的需求做一个统计和预估,一是保证工作 ...

  4. qgis3.16.6+vs2017再编译(debug+release)

    参考 https://www.cnblogs.com/superbi/p/11188145.html 文章以及其它文章,对qggis3.16.6进行了重新编译 一.编译准备 1.Cygwin 1.1安 ...

  5. 常用Java API:Math类

    求最值 最小值 Math.min(int a, int b) Math.min(float a, float b) Math.min(double a, doubleb) Math.min(long ...

  6. SpringCloud微服务实战——搭建企业级开发框架(九):使用Nacos发现、配置和管理微服务

    Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台,Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置 ...

  7. Spring Security:Servlet 过滤器(三)

    3)Servlet 过滤器 Spring Security 过滤器链是一个非常复杂且灵活的引擎.Spring Security 的 Servlet 支持基于 Servlet 过滤器,因此通常首先了解过 ...

  8. Spring源码解读(一):Spring的背景起源及框架整体介绍

    一.前言 Spring起源于2002年Rod Johnson写的一本书<Expert One-on-One J2EE>,书里介绍了Java企业应用程序开发情况,并指出Java EE和EJB ...

  9. hdu 2199 Can you solve this equation?(二分法求多项式解)

    题意 给Y值,找到多项式 8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y 在0到100之间的解. 思路 从0到100,多项式是单调的,故用二分法求解. 代码 double c ...

  10. 基于SpringBoot项目MyBatis分页插件实现分页总结

    前言 在使用Mybatis时,最头痛的就是写分页了,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真的不想花双倍的时间写 count 和 se ...