• BZOJ1096 [ZJOI2007]仓库建设——斜率优化


    方程:

    $Large f(i)=min(f(j)+sumlimits_{k=j+1}^{i}(x_i-x_k)*p_k)+c_i$

    显然这样的方程复杂度为$O(n^3)$极限爆炸,所以我们要换一个方程

    设$S(i)=sumlimits_{k=1}^i(x_n-x_k)*p_k$且$A(i)=sumlimits_{k=1}^ip_k$

    则$S(i)-S(j)=sumlimits_{k=j+1}^i(x_n-x_k)*p_k$,这和原方程很像

    最终方程就可以化成

    $Large f(i)=min(f(j)+S(i)-S(j)-(A(i)-A(j))*(x_n-x_i))+c_i$

    若对于某个$i$,$j$比$k$优,则

    $f(j)+S(i)-S(j)-(A(i)-A(j))*(x_n-x_i)le f(k)+S(i)-S(k)-(A(i)-A(k))*(x_n-x_i)$

    化简得

    $frac{f(j)-S(j)-f(k)+S(k)}{A(j)-A(k)}le x_i-x_n$

    维护一个下凸壳即可

    代码

    #include<cstdio>
    #define LL long long
    #define maxn 1000005
    #define inf 0x3fffffffffffffff
    int x[maxn],p[maxn],c[maxn],que[maxn],s,t=1;
    LL S[maxn],A[maxn],f[maxn];
    LL calc(int i,int j){
        if(A[i]==A[j])return inf;
        return (f[i]-S[i]-f[j]+S[j])/(A[i]-A[j]);
    }
    void insert(int i){
        while(s<t-1&&calc(i,que[t-1])<=calc(que[t-1],que[t-2]))t--;
        que[t++]=i;
    }
    int main(){
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d%d%d",x+i,p+i,c+i),A[i]=A[i-1]+p[i];
        for(int i=1;i<=n;i++){
            S[i]=S[i-1]+1ll*(x[n]-x[i])*p[i];
            while(s<t-1&&calc(que[s+1],que[s])<=x[i]-x[n])s++;
            int w=que[s];
            f[i]=f[w]+S[i]-S[w]-(A[i]-A[w])*(x[n]-x[i])+c[i];
            insert(i);
        }
        printf("%lld",f[n]);
        return 0;
    }
  • 相关阅读:
    程序向informix数据库插入text类型的中文乱码问题
    深入理解Java:注解(Annotation)基本概念
    ssm架构的理解
    队列的java实现
    栈的java实现
    LinkedList的实现原理
    ArrayList的实现
    快速排序
    数据结构之桶排序
    leetcode
  • 原文地址:https://www.cnblogs.com/bennettz/p/9086574.html
Copyright © 2020-2023  润新知