ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-04-21 08:52:21  阅读:412  来源: 互联网

标签:include return int P2365 db batch st FJOI2019 sv


P2365 任务安排

batch:$n<=10000$

斜率优化入门题

$n^{3}$的dp轻松写出

但是枚举这个分成多少段很不方便

我们利用费用提前的思想,提前把这个烦人的$S$在后面的贡献先算掉

设$sv[i],st[i]$为费用、时间的前缀和

于是我们就可以得出一个$n^{2}$的方程

$f[i]=f[j]+(sv[i]-sv[j])*st[i]+(sv[n]-sv[i])*S$

拆开:$f[i]=f[j]+sv[i]*st[i]-sv[j]*st[i]+sv[n]*S-sv[j]*S$

移项:$f[j]=(S+st[i])*sv[j]+f[i]-sv[i]*st[i]-sv[n]*S$

再用$y=k*x+b$的套路带进去

$f[j]=(S+st[i])*sv[j]+f[i]-sv[i]*st[i]-sv[n]*S$

$y=k*x+b$

$y=f[j]$

$x=sv[j]$

$k=S+st[i]$(显然随着$i$增大而单调递增)

$b=f[i]-sv[i]*st[i]-sv[n]*S$

于是问题又转化成:找到一个使$b$最小的$(x,y)$

这样就能使$f[i]$最小

考虑到$k$单调递增,$x$也单调递增

我们就可以快乐地用单调队列维护下凸包辣

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef double db;
#define N 10005
db sv[N],st[N],f[N];
int n,S,L,R,h[N];
inline db X(int x){return sv[x];}
inline db Y(int x){return f[x];}
inline db K(int x,int y){return (Y(x)-Y(y))/(X(x)-X(y));}
int main(){
    scanf("%d%d",&n,&S);
    for(int i=1;i<=n;++i){
        scanf("%lf%lf",&st[i],&sv[i]);
        st[i]+=st[i-1]; sv[i]+=sv[i-1];
    }L=R=1;
    for(int i=1;i<=n;++i){
        while(L<R&&K(h[L],h[L+1])<=S+st[i]) ++L;
        f[i]=f[h[L]]+(sv[i]-sv[h[L]])*st[i]+(sv[n]-sv[h[L]])*S;
        while(L<R&&K(h[R-1],h[R])>K(h[R],i)) --R;
        h[++R]=i;
    }printf("%.0lf",f[n]);
    return 0;
}

 

标签:include,return,int,P2365,db,batch,st,FJOI2019,sv
来源: https://www.cnblogs.com/kafuuchino/p/10743781.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有