• [斜率优化dp] HDU 2829 Lawrence


    题目大意

    传送门

    题解

    (g(L,R)=sum_{i=L}^{R}sum_{j=i+1}^{R}val[i] imes val[j]=frac{1}{2}left(sum_{i=L}^{R}sum_{j=L}^{R}val[i] imes val[j]-sum_{i=L}^R val[i]^2 ight))
    (=frac{1}{2}left(left(sum_{i=L}^R val[i] ight)^2-sum_{i=L}^R val[i]^2 ight))
    (s[n]=sum_{i=1}^{n} val[i])(s2[n]=sum_{i=1}^n val[i]^2)
    (g(L,R)=frac{1}{2}left(left(s[R]-s[L-1] ight)^2-left(s2[R]-s2[L-1] ight) ight))

    (dp[i][j]) 表示前 (i) 个仓库,炸毁 (j) 条铁路的最小价值,
    则有 (dp[i][j]=min{dp[k][j-1]+g(k+1,i)},k<i)

    (g(k+1,i)=frac{1}{2}left(left(s[i]-s[k] ight)^2-left(s2[i]-s2[k] ight) ight)) 代入状态转移方程,
    (dp[i][j]=dp[k][j-1]+frac{1}{2}left(left(s[i]-s[k] ight)^2-left(s2[i]-s2[k] ight) ight))
    整理可得,(2dp[k][j-1]+s[k]^2+s2[k]=2s[i]s[k]+2dp[i][j]+s2[i]-s[i]^2)
    不妨令 (y=2dp[k][j-1]+s[k]^2+s2[k],K=2s[i],x=s[k])
    则原式等于 (y=Kx+2dp[i][j]+s2[i]-s[i]^2)
    发现斜率 (K=2s[i]) 单调递增,显然可以斜率优化,使用单调队列维护一个下凸壳。
    时间复杂度 (O(nm))

    Code

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <cstdio>
    #include <vector>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    template<typename elemType>
    inline void Read(elemType &T){
        elemType X=0,w=0; char ch=0;
        while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
        while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        T=(w?-X:X);
    }
    
    LL Value[1005],dp[1005][1005];
    LL s[1005],s2[1005];
    int Q[1005];
    int N,M,head,tail;
    
    inline LL y(int j,int k){return (dp[k][j-1]<<1)+s[k]*s[k]+s2[k];}
    inline LL x(int k){return s[k];}
    inline LL K(int i){return s[i]<<1;}
    inline LL g(int L,int R){return ((s[R]-s[L-1])*(s[R]-s[L-1])-(s2[R]-s2[L-1]))>>1;}
    inline void maintain(int i,int j,int k){dp[i][j]=dp[k][j-1]+g(k+1,i);}
    
    LL Solve(){
        memset(dp,0x3f,sizeof(dp));
        for(RG i=1;i<=N;++i)
            dp[i][0]=g(1,i);
        for(RG j=1;j<=M;++j){
            dp[j][j]=0;
            head=1;tail=0;
            Q[++tail]=j;
            for(RG i=j+1;i<=N;++i){
                while(tail-head+1>=2){
                    int a=Q[head],b=Q[head+1];
                    if(y(j,b)-y(j,a)<=K(i)*(x(b)-x(a))) ++head;
                    else break;
                }
                maintain(i,j,Q[head]);
                while(tail-head+1>=2){
                    int a=Q[tail-1],b=Q[tail];
                    if((y(j,b)-y(j,a))*(x(i)-x(a))>=(y(j,i)-y(j,a))*(x(b)-x(a))) --tail;
                    else break;
                }
                Q[++tail]=i;
            }
        }
        return dp[N][M];
    }
    
    int main(){
        while(~scanf("%d%d",&N,&M)){
            if(N==0 || M==0) break;
            for(RG i=1;i<=N;++i){
                Read(Value[i]);
                s[i]=s[i-1]+Value[i];
                s2[i]=s2[i-1]+Value[i]*Value[i];
            }
            printf("%lld
    ",Solve());
        }
        return 0;
    }
    
  • 相关阅读:
    webkit 技术内幕 笔记 二
    webkit 技术内幕 笔记 一
    javascript 权威指南1
    正则
    react-virtualized
    移动端字体
    vue 学习3
    vue 学习2
    vue 学习1
    移动端display:flex
  • 原文地址:https://www.cnblogs.com/AEMShana/p/13376890.html
Copyright © 2020-2023  润新知