Batch Scheduling



$ solution: $

这应该是斜率优化中最经典的一道题目,虽然之前已经写过一道 $ catstransport $ 的题解了,但还是来回顾一下吧,这道题其实较那一道还是难一些,只不过 $ catstransport $ 很难找到最好码代码的式子。

首先单调队列优化是用来优化一些转移方程里面存在只与枚举的决策或当前状态中的单独某一个存在关系的项的动态规划,而我们的斜率优化是用来优化一些转移方程里面存在与枚举的决策和当前状态都有直接关系的项的动态规划的(当然斜率优化还需要这个项是随着枚举呈单调性的)。

我们先来分析一下这道题目,要将某些任务按顺序分批次处理,同一批次共用一个时间权值,每批次前要花时间预处理。因为它需要按时间顺序处理,所以我们可以想到线性DP,而且子任务的最优性是可以推广到全局的。可能有人会说最后一个限制会有后效性,但其实它很容易消去,我们只要在每一个批次转移时减去后面所有的任务会因为这个预处理的拖延而产生的额外花费即可。这样我们可以列出转移方程:

因为题目没说一定要将这些任务划分成多少批次,所以我们可以直接设 $ F[i] $ 表示将前 $ i $ 分任务划分完毕之后的最少花费,然后我们预处理处时间的前缀和 $ T[i] $ 还有费用的前缀和 $ S[i] $ 然后转移可以这样:

$ F[i]=^{min}_{0\leq k<j}{F[j]+S\times (S[N]-S[j])+T[i]\times (S[i]-S[j]) } $

这个式子是 $ n^2 $ 的复杂度,数据范围再次对我们说不,我们还要在优化:将与 $ j $ 无关的数提取出来,并去掉括号:

$ F[i]=^{min}_{0\leq k<j}{F[j]+S\times S[N]-S\times S[j]+T[i]\times S[i]-T[i]\times S[j] } $

$ F[i]=^{min}_{0\leq k<j}{F[j]-S\times S[j]-T[i]\times S[j] }+S\times S[N]+T[i]\times S[i] $

然后我们发现 $ max $ 函数里有与枚举的决策 $ j $ 和当前状态 $ i $ 都有直接关系的项 ( $ T[i]\times S[j] $ )而且 $ T[i] $ 是单调递增的,于是我们就可以用斜率优化了。将 $ S[j] $ 最为 $ x $ 轴,将 $ F[i]+S\times S[j] $ 作为 $ y $ 轴,然后每一个决策集合(我们所有的可以用的 $ j $ 都变成一个点),我们知道 $ T[i] $ (斜率)是单调递增的,所以只要这些点的的下凸壳即可!



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set> #define ll long long
#define db double
#define inf 0x7fffffff
#define rg register int using namespace std; int n,s,sr=1;
ll v[300005];
ll t[300005];
ll f[300005];
ll q[300005]; inline int qr(){
register char ch; register bool sign=0; rg res=0;
while(!isdigit(ch=getchar())) if(ch=='-')sign=1;
while(isdigit(ch)) res=res*10+(ch^48),ch=getchar();
return sign?-res:res;
} inline int get(int k){
if(sr<2)return q[sr];
rg l=1,r=sr-1,mid;
while(l<=r){
mid=(l+r)>>1;
if(f[q[mid+1]]-f[q[mid]]<k*(v[q[mid+1]]-v[q[mid]]))l=mid+1;
else r=mid-1;
}return q[l];
} int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=qr(); s=qr();
for(rg i=1;i<=n;++i){
t[i]=t[i-1]+qr();
v[i]=v[i-1]+qr();
} q[1]=0;
for(rg i=1;i<=n;++i){
rg j=get(s+t[i]);
f[i]=f[j]-(s+t[i])*v[j]+v[i]*t[i]+s*v[n];
while(sr>1&&(f[i]-f[q[sr]])*(v[q[sr]]-v[q[sr-1]])<=(f[q[sr]]-f[q[sr-1]])*(v[i]-v[q[sr]])) --sr;
q[++sr]=i;
}printf("%lld\n",f[n]);
return 0;
}

poj 1180 Batch Scheduling (斜率优化)的更多相关文章

  1. POJ 1180 - Batch Scheduling - [斜率DP]

    题目链接:http://poj.org/problem?id=1180 Description There is a sequence of N jobs to be processed on one ...

  2. POJ 1180 Batch Scheduling(斜率优化DP)

    [题目链接] http://poj.org/problem?id=1180 [题目大意] N个任务排成一个序列在一台机器上等待完成(顺序不得改变), 这N个任务被分成若干批,每批包含相邻的若干任务. ...

  3. poj 1180:Batch Scheduling【斜率优化dp】

    我会斜率优化了!这篇讲的超级棒https://blog.csdn.net/shiyongyang/article/details/78299894?readlog 首先列个n方递推,设sf是f的前缀和 ...

  4. POJ 1180 Batch Scheduling

    BTW: 刚在图书馆借了本算法艺术与信息学竞赛. 我多次有买这本书的冲动, 但每次在试看之后就放弃了, 倒不是因为书太难, 而是写的实在是太差. 大家对这本书的评价很高, 我觉得多是因为书的内容, 而 ...

  5. POJ1180 Batch Scheduling -斜率优化DP

    题解 将费用提前计算可以得到状态转移方程: $F_i = \min(F_j + sumT_i * (sumC_i - sumC_j) + S \times (sumC_N - sumC_j)$ 把方程 ...

  6. POJ 1180 Batch Scheduling (dp,双端队列)

    #include <iostream> using namespace std; + ; int S, N; int T[MAX_N], F[MAX_N]; int sum_F[MAX_N ...

  7. P2365 任务安排 / [FJOI2019]batch(斜率优化dp)

    P2365 任务安排 batch:$n<=10000$ 斜率优化入门题 $n^{3}$的dp轻松写出 但是枚举这个分成多少段很不方便 我们利用费用提前的思想,提前把这个烦人的$S$在后面的贡献先 ...

  8. POJ 3709 K-Anonymous Sequence - 斜率优化dp

    描述 给定一个数列 $a$, 分成若干段,每段至少有$k$个数, 将每段中的数减少至所有数都相同, 求最小的变化量 题解 易得到状态转移方程 $F_i = \min(F_j  + sum_i - su ...

  9. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

随机推荐

  1. python 向MySQL里插入中文数据

    用python向MySQL中插入中文数据出错,原代码片段: 1 db = MySQLdb.connect("localhost","root","12 ...

  2. [JSOI2008]最大数 (线段树)

    题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当前数列的长度.(L>=0 ...

  3. 【dp】leetcode Best Time to Buy and Sell Stock IV

    https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/description/ [题意] 给定n天股市的票价,最多交易k次, ...

  4. K大数查询 BZOJ 3110

    K大数查询 [问题描述] 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位 ...

  5. pyquery操作

    pyquery和我们之前用的jQuery有着异曲同工之处,使用起来更加方便,基本能满足大部分时候我们的需求. 先引入一个小事例展示pyquery的操作: html = ''' <div> ...

  6. R语言入门视频笔记--2--一些简单的命令

    一.对象 1.列举当前内存中的对象 ls() 2.删除不需要的对象 rm(某对象名称) 3.查看向量长度 length(某向量名称) 4.查看向量类型 mode(某向量名称) 二.函数 1.seq函数 ...

  7. AFNetworking实时监测网络连接

    
// 网络变化消息 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(checkNetwork) ...

  8. Java搜索引擎选择: Elasticsearch与Solr(转)

    Elasticsearch简介 Elasticsearch是一个实时的分布式搜索和分析引擎.它可以帮助你用前所未有的速度去处理大规模数据. 它可以用于全文搜索,结构化搜索以及分析,当然你也可以将这三者 ...

  9. 使用NSOperationQueue简化多线程开发

    多线程开发是一件需要特别精心的事情,即使是对有多年开发经验的工程师来说. 为了能让初级开发工程师也能使用多线程,同时还要简化复杂性.各种编程工具提供了各自的办法.对于iOS来说,建议在尽可能的情况下避 ...

  10. 【Linux】在虚拟机上安装ubuntu

    虚拟机安装步骤  参考:http://www.cnblogs.com/sxdcgaq8080/p/7466529.html 在安装ubuntu系统之前,当然是下载一个ubuntu的iso镜像在本地啦. ...