链接:

P5785

弱化版:P2365


题意:

有 \(n\) 个任务待完成,每个任务有一个完成时间 \(t_i\) 和费用系数 \(f_i\),相邻的任务可以被分成一批。从零时刻开始这些任务会被机器分批完成,在每批任务开始前机器有一个给定启动时间 \(s\),一批任务的完成时间是这批任务完成时间之和,同一批任务视作在同一时刻完成。

每个任务的费用是他的完成时刻和费用系数的乘积,请最小化总费用。


分析:

如果设 \(dp[i]\) 为第 \(i\) 个任务作为当前这一批任务的最后一个时的最优解,这样会很麻烦,因为会涉及到 "此时一共有多少批" 这个很麻烦的状态。这里有一个dp的trick费用提前

我们发现把第 \(i\) 个任务作为当前这一批任务的最后一个时,当前批内以及后面的任务都会多一个 \(s\cdot f_i\) 的费用,于是把 \(dp[i]\) 改为第 \(i\) 个任务作为当前这一批任务的最后一个时,加上后面任务的已有贡献的最优解。可以联系状态转移理解:

\[dp[i]=dp[j]+(\sum_{k=j+1}^if_i\times\sum_{k=1}^it_i)+s\sum_{k=j+1}^nf_i
\]

于是设 \(sumf[i]=\sum\limits_{k=1}^if_k\),\(sumt[i]=\sum\limits_{k=1}^it_k\)

\[dp[i]=dp[j]+(sumf[i]-sumf[j])\times sumt[i]+s(sumf[n]-sumf[j])
\]

于是

\[dp[i]=dp[j]+sumf[i]sumt[i]-sumf[j]sumt[i]+s\cdot sumf[n]-s\cdot sumf[j]
\]

依套路:

\[(dp[j]-s\cdot sumf[j])=sumt[i]sumf[j]+(dp[i]-sumf[i]sumt[i]-s\cdot sumf[n])
\]

于是求斜率为 \(sumt[i]\),过点 \((sumf[j],dp[j]-s\cdot sumf[j])\) 的直线的最小截距。

这里的 \(sumt[i]\) 并不是单调的,所以不能用单调队列优化,一个优秀的办法是二分找到第一个与下一个点之间的斜率大于 \(sumt[i]\) 的点,时间复杂度 \(O(n\log n)\)。


算法:

单调队列维护下凸包,然后每次二分找到最优决策点,根据其信息得到 \(dp[i]\),继续维护凸包即可。时间复杂度 \(O(n\log n)\)。


重要的细节:

这道题让我注意到了一个斜率优化dp中的一个很重要的细节,就是维护下凸包的判断。

这道题在洛谷讨论区也有不少人曾发起过讨论,称因为精度问题而必须把判断斜率改成乘法,但其实并不是这样一个简单的借口,我们来看下面三个代码,他们除了维护下凸包的判断没有任何区别。

(Y(q[qt])-Y(q[qt-1]))*(X(i)-X(q[qt])) >= (Y(i)-Y(q[qt]))*(X(q[qt])-X(q[qt-1])) 100pts

slope(q[qt],q[qt-1])>=slope(i,q[qt]) 80pts

slope(q[qt],q[qt-1])>=slope(i,q[qt-1]) 100pts

显然,这并不是精度的问题,甚至这三种写法都是错的!

我们来看下面这种情况:(这种情况虽然在数据上比较难构造,但单纯考虑维护下凸包来看还是很常见的)

这样三个横坐标相等点从上到下按 \(1,3,2\) 的次序被加入下凸包的维护。

显然,根据人脑判断,这样的数据要维护下凸包自然是保留 \(2\) 号点,弹出 \(3\) 号点,但普遍的写法是不存在 "弹出当前点" 这种操作的,只有 "弹出上一个点"。于是:

如果是第一种判断,两边的乘积都是 \(0\),于是会弹出 \(2\) 号点,此时 \(1,3\) 点间斜率为 -inf,后面的点可以加入,但在局部确实出现了正确性的错误。

如果是第二种判断,由于 \(1,2\) 间斜率是 -inf,\(2,3\) 点间斜率是 +inf,所以不会有点弹出,此时 \(2,3\) 点之间斜率为 +inf,这种情况下,后面的点根本无法加入下凸包的维护了,出现了严重的问题。

如果是第三种判断,由于 \(1,2\) 间斜率是 -inf,\(1,3\) 点间斜率是 -inf,这里也涉及取等的问题,如果取等,那么会弹出 \(2\) 号点,变成第一种情况;如果不取等,那么 \(2\) 号点不会被弹出,于是变成第二种情况。

所以这题错误的真正原因根本不是什么精度,而是维护下凸包的做法在存在横坐标相等的情况下本来就是假的!

根据这题横坐标非严格单调增,一个感觉比较正确的做法是在维护下凸包时先判断与前面的点横坐标是否相等,如果相等,保留纵坐标最低的点;如果不等,按照原本的做法即可。

在这样的做法下,不等号是否取等是没有正确性的影响的。取等会弹出一些无用的点,可能会快几毫秒。

所以在有横坐标相等的情况下,一个正确的写法是:

if(X(i)==X(q[qt])&&1<qt){if(Y(i)<Y(q[qt]))qt--;else continue;}
while(1<qt&&slope(q[qt],q[qt-1])>=slope(i,q[qt]))qt--;
q[++qt]=i;

这样写的话,不管判断是用的乘法还是斜率,哪两个斜率判断,或者取不取等,都是能过的。不排除真的会有精度错误,但我认为不能把根据观察发现除法比乘法劣的情况统一归咎到精度错误上。


代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
inline int read(){
int p=0,f=1;
char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){p=p*10+c-'0';c=getchar();}
return p*f;
}
#define X(x) (sumf[x])
#define Y(x) (dp[x]-sumf[x]*s)
#define dx(x,y) (X(x)-X(y))
#define dy(x,y) (Y(x)-Y(y))
#define slope(x,y) ((double)dy(x,y)/dx(x,y))
const int N=3e5+5;
const int inf=0x7fffffffffffffff;
int n,s,t[N],f[N],sumt[N],sumf[N],dp[N],q[N],qt;
inline int bin(int key){
int l=1,r=qt,mid;
while(l<r){
mid=(l+r)>>1;
double cp=(mid==qt)?inf:slope(q[mid+1],q[mid]);
if(cp<key)l=mid+1;
else r=mid;
}
return l;
}
signed main(){
n=in,s=in;
for(int i=1;i<=n;i++)
t[i]=in,f[i]=in,
sumt[i]=sumt[i-1]+t[i],
sumf[i]=sumf[i-1]+f[i];
qt=1;
for(int i=1;i<=n;i++){
int qh=bin(sumt[i]);
dp[i]=Y(q[qh])-sumt[i]*X(q[qh])+sumf[i]*sumt[i]+sumf[n]*s;
if(X(i)==X(q[qt])&&1<qt){if(Y(i)<Y(q[qt]))qt--;else continue;}
while(1<qt&&slope(q[qt],q[qt-1])>slope(i,q[qt-1]))qt--;
q[++qt]=i;
}
cout<<dp[n];
return 0;
}

题外话:

这个重要的细节确实让我对斜优里维护下凸包部分的印象深了许多。

洛谷 P5785 [SDOI2012] 任务安排的更多相关文章

  1. 洛谷P2751[USACO]工序安排

    题目传送门 怎么说呢,这个题目我刚开始随便乱搞了几下,交了个暴力代码上去居然还水了49分,数据确实有点弱啊,然后看到洛谷上那位大佬Redbag的题解瞬间就佩服的五体投地,那真的是简洁.易懂又高效.直接 ...

  2. 洛谷P2365/5785 任务安排 题解 斜率优化DP

    任务安排1(小数据):https://www.luogu.com.cn/problem/P2365 任务安排2(大数据):https://www.luogu.com.cn/problem/P5785 ...

  3. 洛谷 P2303 [SDOi2012]Longge的问题 解题报告

    P2303 [SDOi2012]Longge的问题 题目背景 SDOi2012 题目描述 Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题.现在问题来了:给定一个整数\(N\),你需要 ...

  4. 洛谷 P2498 [SDOI2012]拯救小云公主 解题报告

    P2498 [SDOI2012]拯救小云公主 题目描述 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到\(boss\)的洞穴门口,他一下子就懵了,因为面前不只是一 ...

  5. 洛谷P2303 [SDOi2012]Longge的问题

    题目背景 SDOi2012 题目描述 Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题.现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N). ...

  6. 洛谷 P2837 晚餐队列安排

    P2837 晚餐队列安排 题目背景 Usaco Feb08 Bronze 题目描述 为了避免餐厅过分拥挤,FJ要求奶牛们分2批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想,所有第2批就餐 ...

  7. 洛谷P2303 [SDOi2012] Longge的问题 数论

    看懂了题解,太妙了TT但是想解释的话可能要很多数学公式打起来太麻烦了TT所以我就先只放代码具体推演的过程我先写在纸上然后拍下来做成图片放上来算辣quq 好的那我先滚去做题了做完这题就把题解放上来.因为 ...

  8. 洛谷P2351 [SDOi2012]吊灯 【数学】

    题目 Alice家里有一盏很大的吊灯.所谓吊灯,就是由很多个灯泡组成.只有一个灯泡是挂在天花板上的,剩下的灯泡都是挂在其他的灯泡上的.也就是说,整个吊灯实际上类似于[b]一棵树[/b].其中编号为 1 ...

  9. 洛谷P2498 [SDOI2012]拯救小云公主 【二分 + 并查集】

    题目 英雄又即将踏上拯救公主的道路-- 这次的拯救目标是--爱和正义的小云公主. 英雄来到boss的洞穴门口,他一下子就懵了,因为面前不只是一只boss,而是上千只boss.当英雄意识到自己还是等级1 ...

随机推荐

  1. Spring Cloud Gateway 学习+实践

    官网上给出的Spring Cloud Gateway特性如下图所示: 翻译过来就是: 基于 Spring Framework 5 ,Project Reactor 以及 Spring Boot 2.0 ...

  2. 论文解读(PCL)《Prototypical Contrastive Learning of Unsupervised Representations》

    论文标题:Prototypical Contrastive Learning of Unsupervised Representations 论文方向:图像领域,提出原型对比学习,效果远超MoCo和S ...

  3. python IO流操作

    python IO流操作 学习完本篇,你将会独立完成 实现操作系统中文件及文件目录的拷贝功能. 将目标图片拷贝到指定的目录中 实现一个自动阅卷程序, Right.txt保存正确答案,xx(学生姓名). ...

  4. 让PHP能够调用C的函数-FFI扩展

    在大型公司中,一般会有很我编程语言的配合.比如说让 Java 来做微服务层,用 C++ 来进行底层运算,用 PHP 来做中间层,最后使用 JS 展现效果.这些语言间的配合大部分都是通过 RPC 来完成 ...

  5. PHP操作用户提交内容时需要注意的危险函数

    对于我们的程序开发来说,用户的输入是解决安全性问题的第一大入口.为什么这么说呢?不管是SQL注入.XSS还是文件上传漏洞,全部都和用户提交的输入参数有关.今天我们不讲这些问题,我们主要探讨下面对用户的 ...

  6. 阿里云短信功能php

    1. 引入文件: https://help.aliyun.com/document_detail/53111.html?spm=a2c1g.8271268.10000.99.5a8ddf25gG0wW ...

  7. 小学生都能读懂的网络协议之:WebSocket

    目录 简介 webSocket vs HTTP HTTP upgrade header websocket的优点 webScoket的应用 websocket的握手流程 WebSocket API 总 ...

  8. python pip 安装使用国内镜像源

    国内镜像源 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ 中国科技大学 ...

  9. HttpRunner3.X - 全面讲解如何落地项目实战

    一.前言 接触httprunner框架有一段时间了,也一直探索如何更好的落地到项目上,本篇主要讲述如何应用到实际的项目中,达到提升测试效率的目的. 1.项目难题 这个月开始忙起来了,接了个大项目,苦不 ...

  10. Midway Serverless 发布 2.0,一体化让前端研发再次提效

    作者 | 张挺 来源 | Serverless 公众号 自去年 Midway Serverless 1.0 发布之后,许多业务开始尝试其中,并利用 Serverless 容器的弹性能力,减少了大量研发 ...