[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个任务被分成若 ...
随机推荐
- mika的模板库
二分图最大匹配: 1.匈牙利算法:注意dfs中是dfs(c[w[i]]),搜索的是与之匹配的点. #include<cstdio> #include<cstring> ],w[ ...
- Centos7下安装配置elasticsearch 6.3.1
1)下载 Elasticsearch 6.3.1 地址:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.1 ...
- Python的伪造数据生成器:Faker
我们在开发中常常需要利用一些假数据来做测试,这种时候就可以使用 Faker 来伪造数据从而用来测试. Faker 是一个可以让你生成伪造数据的Python包.当你需要初始化数据库,创建美观的XML文档 ...
- (Review cs231n) CNN in Practice
Make the most of your data Data augmentation 加载图像后,对图像做一些变化,这些变换不改变图像的标签. 通过各种变换人为的增大数据集,可以避免过拟合提高模型 ...
- 前端使用node.js的http-server开启一个本地服务器
前端使用node.js的http-server开启一个本地服务器 在写前端页面中,经常会在浏览器运行HTML页面,从本地文件夹中直接打开的一般都是file协议,当代码中存在http或https的链接时 ...
- ie8下new Date()指定时间
项目开发中很可能会需要创建一个指定日期的时间对象,火狐浏览器可以直接使用new Date('yyyy-mm-dd')生成时间,但是在ie8下就会发现生成的时间输出的是NaN-NaN-NaN.为了兼容可 ...
- 获取某个元素第一次出现在数组(json数组)的索引
function firstIndex(arr, text) { // 若元素不存在在数组中返回-1 let firstVal = -1; for (let i = 0; i < arr.len ...
- 小试wsl
安装 管理员权限运行powershell,执行如下命令: Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Su ...
- opencv学习之路(41)、人脸识别
一.人脸检测并采集个人图像 //take_photo.cpp #include<opencv2/opencv.hpp> using namespace cv; using namespac ...
- 详解Bootstrap实现基本布局的方法
看到了一篇 20 分钟打造 Bootstrap 站点的文章,内容有点老,重新使用bootstrap教程实现一下,将涉及的内容也尽可能详细说明. 1. 创建基本的页面我们先创建一个基本的 HTML 模板 ...