• bzoj3156 防御准备(斜率优化)


    Time Limit: 10 Sec  Memory Limit: 512 MB

     

    Input

    第一行为一个整数N表示战线的总长度。

    第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai。

    Output

    共一个整数,表示最小的战线花费值。

    Sample Input

    10
    2 3 1 5 4 5 6 3 1 2

    Sample Output

    18

    HINT

    1<=N<=10^6,1<=Ai<=10^9


    设$f[i]$为已经完成$i+1$到$n$,在$i$放塔的最小代价

    $f[i]=a[i]+min(f[j]+ frac {(j-i-1)(j-i)}{2}),i<j<=n$

    移项转化,得

    $f[j]+frac{j(j-1)}{2}=ij+f[i]-frac{i(i+1)}{2}$

    $k=i,x=j$单调

    凸包维护单调队列,复杂度$O(n)$

    #include<cstdio>
    typedef long long ll;
    inline ll min(ll A,ll B){return A<B?A:B;}
    inline ll max(ll A,ll B){return A>B?A:B;}
    int read(){
        char c=getchar(); int x=0;
        while(c<'0'||c>'9') c=getchar();
        while('0'<=c&&c<='9') x=x*10+c-48,c=getchar();
        return x;
    }
    #define N 1000005
    int n,a[N],h[N],L,R; ll f[N],ans=1e16;
    inline ll y(ll j){return f[j]+j*(j-1)/2;}
    inline int chk(ll A,ll B,ll kx,ll ky){return (y(A)-y(B))*kx>=ky*(A-B);}
    int main(){
        R=n=read();
        for(register int i=1;i<=n;++i) a[i]=read();
        f[n]=a[n]; h[L=R=1]=n;
        for(register ll i=n-1;i;--i){
            while(L<R&&chk(h[L],h[L+1],1,i)) ++L;
            f[i]=a[i]+f[h[L]]+(h[L]-i)*(h[L]-i-1)/2;
            while(L<R&&chk(h[R],h[R-1],h[R]-i,y(h[R])-y(i))) --R;
            h[++R]=i;
            ans=min(ans,f[i]+i*(i-1)/2);
        }printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    bzoj5253 [2018多省省队联测]制胡窜
    bzoj5249 [2018多省省队联测]IIIDX
    bzoj5248 [2018多省省队联测]一双木棋
    HEOI2018 游记
    bzoj2720 [Violet 5]列队春游
    bzoj4871 [Heoi2017]摧毁“树状图”
    bzoj3991 [SDOI2015]寻宝游戏
    bzoj3598 [Scoi2014]方伯伯的商场之旅
    Flash平台的分析与RIA的趋势
    JavaScript的变量预解析特性
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/11503195.html
Copyright © 2020-2023  润新知