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


    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[j])*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;
    }
  • 相关阅读:
    luogu P2639 [USACO09OCT]Bessie的体重问题Bessie's We…
    1001. 害死人不偿命的(3n+1)猜想 (15)
    1003. 我要通过!(20)
    1002. 写出这个数 (20)
    《C语言程序设计(第四版)》阅读心得(一)
    1006. 换个格式输出整数 (15)
    背包问题之多重背包
    背包问题之完全背包
    背包问题之0-1背包
    动态规划例题
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/10743781.html
Copyright © 2020-2023  润新知