zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    【编程题目】左旋转字符串 ☆
    360測试开发笔试题(2016内推)
    start_kernel——boot_cpu_init及PER_CPU
    UVa 10673
    【面试】-Java基础知识
    Navgationcontroller 的pop
    别拿接口不当开发
    C++基础学习教程(三)
    安卓版微信自带浏览器和IE6浏览器ajax请求abort错误处理
    【动态树问题】LCT学习笔记
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/11503195.html
Copyright © 2011-2022 走看看