• 【BZOJ2726】【SDOI2012】—任务安排(斜率优化dp)


    传送门

    有一个显然的O(n2)dpO(n^2)dp

    f[i]f[i]表示前ii天的最小花费
    tottot是费用的前缀和
    tt是时间的前缀和

    f[i]=min(f[j]+(totntotj)(s+titj))f[i]=min(f[j]+(tot_n-tot_j)*(s+t_i-t_j))
    g[i]=f[i]totnti+totitistotjg[i]=f[i]-tot_n*t_i+tot_i*t_i-s*tot_j

    考虑2个决策点如果xxyy更优
    g[x]g[y]totxtotytifrac{g[x]-g[y]}{tot_x-tot_y}le ti

    那就变成斜率优化的套路了

    注意斜率不要直接除,精度要爆炸的
    交叉相乘判大小

    BZOJBZOJdoubledouble很友好?比long longlong long快了接近一倍

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    #define ll long long
    #define re register
    inline char gc(){
    	static char ibuf[RLEN],*ob,*ib;
    	(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ob==ib)?EOF:*ib++;
    }
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=(ch=='-'),ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    const int N=300005;
    const double eps=1e-6;
    struct point{
        double x,y;
        point(double _x=0,double _y=0):x(_x),y(_y){}
        friend inline point operator -(const point &a,const point &b){
            return point(a.x-b.x,a.y-b.y);
        }
        inline double slope(){
            return x/y;
        }
    }p[N];
    int n,stk[N],top;
    ll f[N],s,tot[N],t[N];
    inline void dp(int i,int j){
        f[i]=f[j]+(t[i]-t[j]+s)*(tot[n]-tot[j]);
    }
    signed main(){
        n=read(),s=read();
        for(re int i=1;i<=n;++i)t[i]=t[i-1]+read(),tot[i]=tot[i-1]+read();
        for(re int i=1;i<=n;++i){
            re int l=1,r=top,res=0;
            while(l<=r){
                int mid=(l+r)>>1;
                point tp=(p[stk[mid]]-p[stk[mid-1]]);
                if(tp.y<=t[i]*tp.x)l=mid+1,res=mid;
                else r=mid-1;
            }
            dp(i,stk[res]);
            p[i].x=tot[i],p[i].y=f[i]-tot[n]*t[i]+tot[i]*t[i]-s*tot[i];
            while(top&&(p[stk[top]]-p[stk[top-1]]).y*(p[i]-p[stk[top]]).x>=(p[i]-p[stk[top]]).y*(p[stk[top]]-p[stk[top-1]]).x)top--;
            stk[++top]=i;
        }
        cout<<f[n];
    }
    
  • 相关阅读:
    asp.net Forms验证跨域页面不能访问的问题
    JavaScript创建命名空间
    DataTable转换成JSON字符串的函数
    javascript 正确截取单字节和双字节混和字符串的方法
    异常详细信息: 不能通过已删除的行访问该行的信息
    HttpUtility.ParseQueryString直接从字符串URL中提取参数
    支持函数,变量的算术表达式计算(三、加入函数)
    mp3 分类管理工具
    我好累
    电饭煲是如何知道饭已熟了的
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145570.html
Copyright © 2020-2023  润新知