[bzoj P2726] [SDOI2012]任务安排
[bzoj P2726] [SDOI2012]任务安排
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 1204 Solved: 349
[Submit][Status][Discuss]
Description机器上有N个需要处理的任务,它们构成了一个序列。这些任务被标号为1到N,因此序列的排列为1,2,3...N。这N个任务被分成若干批,每批包含相邻的若干任务。从时刻0开始,这些任务被分批加工,第i个任务单独完成所需的时间是Ti。在每批任务开始前,机器需要启动时间S,而完成这批任务所需的时间是各个任务需要时间的总和。注意,同一批任务将在同一时刻完成。每个任务的费用是它的完成时刻乘以一个费用系数Fi。请确定一个分组方案,使得总费用最小。
Input第一行两个整数,N,S。
接下来N行每行两个整数,Ti,Fi。
Output一个整数,为所求的答案。
Sample Input5 1
1 3
3 2
4 3
2 3
1 4
Sample Output153
没有数据范围,差评!
自己从discuss里面搞来了:
[1, 4] 0<N<=1000 0<=S<=2^8 0<=Ti<=2^8 0<=Fi<=2^8
[5, 12] 0<N<=300000 0<=S<=2^8 0<=Ti<=2^8 0<=Fi<=2^8
[13, 20] 0<N<=100000 0<=S<=2^8 -(2^8)<=Ti<=2^80<=Fi<=2^8
看这数据范围。。
刚开始还没有想到???吃枣药丸
这题如果我们正推需要二维,最坏O(n^3),最好O(n^2),过不了啊。。
但是如果逆着来——(一下我把F数组写成g数据,个人习惯,不喜勿喷)
f[i]=min(f[j]+s*g[j]+(s+t[i]-t[j])*(g[i]-g[j])+(t[i]-t[j])*g[j])=min(f[j]+(s+t[i]-t[j])*g[i])
其中,g数组和t数组都是后缀和。
为了方便处理,我们把整个reverse一下,然后就是正常的从前往后推了。
显然,这东西很适合推斜率优化。
设k<j<i,更新f[i]时f[j]比f[k]优越当且仅当f[j]+(s+t[i]-t[j])*g[i]<f[k]+(s+t[i]-t[k])*g[i]
变形得,
(f[i]-f[k])/(t[j]-t[k])<g[i]
哈哈哈,这不就一sb题吗,g[i]递增啊。
然而出题人就这么毒瘤,时间t搞成还有负数和0,所以t数组就不是单调的了。
这。。。据说x坐标不单调要平衡树或cdq啊。。。完了。
1min。
2min。
3min。
……
nhours。。。
死磕了一下别的dalao的blog,终于会了。
这里运用cdq的思想主要还是在归并排序上面。
通过构造x坐标有序的凸包来更新解。
显然,用分治来做,处理[l..r]时先把[l..mid]搞成x坐标有序的(当然要先把这段区间的答案计算出来,即先cdq(l,mid)),
然后可以构造出一个凸包,供[mid+1..r]这段区间使用。
更新好以后[mid+1..r],并不意味着[mid+1..r]的答案确定了,因为这本段区间里点还没有被本段区间的点更新过。
所以还要调用cdq(mid+1,r)。
然后最后把区间按照t从小到大排好序。
当然,在熟练之后,很容易能推出要维护一个斜率单调递增的队列(也就是下凸壳)。
续了我。。。
据说还有一种方法,能使x坐标单调,斜率不单调?留坑。
upd:12/4 19:24
明白了怎么用二分处理。当然用二分是在斜率不单调的时候用的。
那我们就要改一下这个方程:
这里(其实上面也有)运用到了“提前计算代价”的思想。
就是说,在不影响dp的无后效性的情况下,转移当前状态时,将当前影响到后面的费用计算出来。
方程:f[i]=min{f[j]+s*(g[n]-g[j])+t[i]*(g[i]-g[j])}
其中g和t都是前缀和。这个方程转自konjac大佬的博客。
然后设k<j<i,f[j]<f[k],
则(f[j]-f[k])/(g[j]-g[k])<s+t[i]。
而g是递增的,s+t[i]则不是。
这时我们不需要cdq了,但需要二分。
怎么二分?
我们发现维护的还是一个斜率单调递增的凸包,但是查询的时候,可不能和原来那样,秉承一个单调的原则取了。
因为原来如果s+t[i]是递增的,那么你删掉了一个点q[c],那么表示slope(q[c],q[c+1])<s+t[i],那对于更大的s+t[i],这个点就没有用了,直接pop掉就好了。
但是现在情况不同,不能pop。那么,我们可以查找一个ret点,使ret是满足slope(q[ret],q[ret+1)>=s+t[i]的点中,slope(q[ret],q[ret+1)最小的一个。
换言之,就是最靠前的那一个。那我们可以通过二分查找来实现,不过需要判断边界情况。
复杂度仍然是O(nlogn)的。
code(cdq):
#include <cstdio> #include <cstring> #include <algorithm> typedef long long LL; using namespace std; void OJ() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif } namespace fastIO { #define gec(c) getchar(c) #define puc(c) putchar(c) char ch; inline int read() { ,f=; ch=getchar(); ') { if (ch=='-') f=-f; ch=gec(); } ') { x=(x<<)+(x<<)+(ch^); ch=getchar(); } return x*f; } ]; template <class T> inline void write(T x) { ) { puc('); return; } ) x=-x,puc('-'); ; x; x/=) nnn[++ttt]=x%; ); } } using namespace fastIO; ; int n,L,R; LL s; struct point { LL x,y; point () {} point (LL i,LL j) : x(i),y(j) {} } q[N]; struct mis { int i; LL t,g,v,f; } a[N],o[N]; inline double slope (point u,point v) { ?1e10:-1e10; return 1.0*(v.y-u.y)/(v.x-u.x); } inline void insert (point u) { for ( ; L<R; ) { ],q[R])>slope(q[R],u)) { --R; } else break; } q[++R]=u; } inline LL reply (LL k) { for ( ; L<R; ) { ])<1.0*k) { ++L; } else break; } return q[L].y-k*q[L].x; } #define M ((l)+(r)>>1) inline void cdq (int l,int r) { if (l>=r) return; cdq(l,M); L=,R=; for (int i=l; i<=M; ++i) { insert(point(a[i].t,a[i].f)); } ; i<=r; ++i) { a[i].f=min(a[i].f,reply(a[i].g)+a[i].v); } cdq(M+,r); ; for (int i=l; i<=r; ++i) { if (v>r||(a[u].t<a[v].t&&u<=M)) o[i]=a[u++]; else o[i]=a[v++]; } for (int i=l; i<=r; ++i) a[i]=o[i]; } inline bool cmp (const mis &u,const mis &v) { return u.i<v.i; } int main() { OJ(); n=read(),s=read(); ; i<=n; ++i) { a[i].t=read(),a[i].g=read(); a[i].i=n-i+; } for (int i=n; i; --i) { a[i].t+=a[i+].t,a[i].g+=a[i+].g; a[i].f=a[i].v=(s+a[i].t)*a[i].g; } reverse(a+,a++n); cdq(,n); sort(a+,a++n,cmp); write(a[n].f); ; }code(二分):
#include <cstdio> #include <cstring> #include <algorithm> typedef long long LL; using namespace std; void OJ() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif } namespace fastIO { #define gec(c) getchar(c) #define puc(c) putchar(c) char ch; inline int read() { ,f=; ch=getchar(); ') { if (ch=='-') f=-f; ch=gec(); } ') { x=(x<<)+(x<<)+(ch^); ch=gec(); } return x*f; } ]; template <class T> inline void write(T x) { ) { puc('); return; } ) x=-x,puc('-'); ; x; x/=) nnn[++ttt]=x%; ); } } using namespace fastIO; ; const LL inf=1e12; int n,L,R; LL s; struct point { LL x,y; point () {} point (LL i,LL j) : x(i),y(j) {} } q[N],opt; struct mis { LL t,g,f; } a[N]; inline double slope (point u,point v) { if (v.x==u.x) return v.y>u.y?inf:-inf; return 1.0*(v.y-u.y)/(v.x-u.x); } inline void insert (point u) { for ( ; L<R; ) { ],q[R])>=slope(q[R],u)) { --R; } else break; } q[++R]=u; } inline point reply (LL k) { if (L==R) return q[L]; else ],q[R])<k) return q[R]; else ])>=k) return q[L]; ,mid,ret; while (l<=r) { mid=(l+r)>>; ])>=k) { ret=mid,r=mid-; } ; } return q[ret]; } int main() { OJ(); n=read(),s=read(),a[].t=a[].g=a[].f=; ; i<=n; ++i) a[i].t=read(),a[i].g=read(); ; i<=n; ++i) a[i].t+=a[i-].t; ; i<=n; ++i) a[i].g+=a[i-].g; L=,R=,q[]=point(,); ; i<=n; ++i) { LL k=s+a[i].t; opt=reply(k); a[i].f=opt.y-k*opt.x+s*a[n].g+a[i].t*a[i].g; insert(point(a[i].g,a[i].f)); } write(a[n].f); ; }
[bzoj P2726] [SDOI2012]任务安排的更多相关文章
- BZOJ 2726: [SDOI2012]任务安排( dp + cdq分治 )
考虑每批任务对后面任务都有贡献, dp(i) = min( dp(j) + F(i) * (T(i) - T(j) + S) ) (i < j <= N) F, T均为后缀和. 与j有关 ...
- BZOJ 2726: [SDOI2012]任务安排 [斜率优化DP 二分 提前计算代价]
2726: [SDOI2012]任务安排 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 868 Solved: 236[Submit][Status ...
- bzoj 2726: [SDOI2012]任务安排【cdq+斜率优化】
cdq复健.jpg 首先列个n方递推,设sf是f的前缀和,st是t的前缀和: \[ f[i]=min(f[j]+s*(sf[n]-sf[j])+st[i]*(sf[i]-sf[j])) \] 然后移项 ...
- bzoj 2726: [SDOI2012]任务安排
Description 机 器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这N个任务被分成若干批,每批包含相邻的 若干任务.从时刻0开始,这 ...
- BZOJ.2726.[SDOI2012]任务安排(DP 斜率优化)
题目链接 数据范围在这:https://lydsy.com/JudgeOnline/wttl/thread.php?tid=613, 另外是\(n\leq3\times10^5\). 用\(t_i\) ...
- BZOJ 2726 [SDOI2012] 任务安排 - 斜率优化dp
题解 转移方程与我的上一篇题解一样 : $S\times sumC_j + F_j = sumT_i \times sumC_j + F_i - S \times sumC_N$. 分离成:$S\t ...
- bzoj 2726 [SDOI2012]任务安排(斜率DP+CDQ分治)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2726 [题意] 将n个任务划分成若干个块,每一组Mi任务花费代价(T+sigma{ t ...
- BZOJ 2726: [SDOI2012]任务安排 斜率优化 + 凸壳二分 + 卡精
Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) # ...
- 【BZOJ2726】[SDOI2012]任务安排 斜率优化+cdq分治
[BZOJ2726][SDOI2012]任务安排 Description 机器上有N个需要处理的任务,它们构成了一个序列.这些任务被标号为1到N,因此序列的排列为1,2,3...N.这N个任务被分成若 ...
随机推荐
- CentOS-7.3 设置静态 ip
1. VMnet8 必须设置固定 ip,否则会发生:虚拟机可以访问主机和外网,但是主机 windows 却访问不了虚拟机 2. 虚拟网络编辑器设置网关 IP(G): 必须与 VMnet8 的 ip 在 ...
- Java面试题整理---网络篇
1.BIO.AIO和NIO的概念及区别? 2.什么是长连接和短连接? 3.http1.0.http1.1和http2.0的区别? 4.https和http的区别? 5.https的工作原理? ...
- ABP入门系列之3——创建实体/Code First创建数据表
一.首先来看看ABP体系结构 领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现.实体(Entity): 实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表.仓储(Repo ...
- 什么是DevOps
历史回顾 为了能够更好的理解什么是DevOps,我们很有必要对当时还只有程序员(此前还没有派生出开发者,前台工程师,后台工程师之类)这个称号存在的历史进行一下回顾. 如编程之道中所言: 老一辈的程序员 ...
- 打开visual studio 2010报错:未能正确加载“VSTS for Database Professionals Sql Server Data-tier Application”包
1 解决: 运行cmd 2 输入:regsvr32 %windir%\system32\jscript.dll
- Java8-对map过滤
1.对map按值过滤返回值 public class TestMapFilter { public static void main(String[] args) { Map<Integer, ...
- js filter 数组去重
let arr = [1, 2, 3, 10, 4, 5, 1, 3, 5]; let stateNumArr = arr.filter((item, index, array) => { re ...
- Java线程池ThreadPoolExecutor原理和用法
1.ThreadPoolExecutor构造方法 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAli ...
- kubernets controller 和 CRD的扩展
sample git repo 各个组件开发指导 operator 介绍 此图来自谷歌员工的实践介绍 client-go的使用和源码分析 (dlv) p pods *k8s.io/api/core/v ...
- Linux coredump解决流程
一.打开core文件限制 a.sudo vi /etc/profile b.文件末尾添加ulimit -c unlimited source /etc/profile 把文件重新加载到内存 c.roo ...