zoukankan      html  css  js  c++  java
  • BZOJ 3156: 防御准备

    传送门

    这一题看一眼就是 $dp$,发现限制是在右边,不妨把数列反过来,这样限制在左边比较舒服

    然后显然地设 $f[i]$ 表示位置 $i$ 强制放守卫时控制 $[1,i]$ 的最小费用

    那么转移直接枚举上一个守卫 $j$,因为之间放置木偶的花费为 $1+2+...+(i-j-1)=(i-j-1)(i-j)/2$,有转移:

    $f[i]=f[j]+a[i]+(i-j-1)(i-j)/2$

    发现后面这个是个二次函数,考虑斜率优化

    把式子拆开,$f[i]=f[j]+a[i]+(i^2-i)/2+(j^2+j)/2-ij$,移项得 $f[j]+(j^2+j)/2=ij+f[i]-a[i]-(i^2-i)/2$

    那么 $y=f[j]+(j^2+j),k=i,x=j,b=f[i]-a[i]-(i^2-i)/2$,因为 $k,x$ 都单调,直接斜率优化即可

    最后答案是 $f[n+1]$ ,因为 $f[i]$ 表示 $i$ 强制放守卫

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e6+7;
    int n,a[N];
    ll f[N];
    int Q[N],L,R;
    inline int X(int j) { return j; }
    inline int Y(int j) { return f[j]+(1ll*j*j+j)/2; }
    inline ll calc(int i,int j) { return f[j]+a[i]+1ll*(i-j-1)*(i-j)/2; }
    inline long double slope(int i,int j) { return (long double)(Y(i)-Y(j))/(X(i)-X(j)); }
    int main()
    {
        n=read(); for(int i=1;i<=n;i++) a[i]=read();
        reverse(a+1,a+n+1); L=R=1; Q[L]=1; f[1]=a[1];
        for(int i=2;i<=n+1;i++)
        {
            while(L<R && calc(i,Q[L])>=calc(i,Q[L+1])) L++;
            f[i]=calc(i,Q[L]);
            while(L<R && slope(Q[R-1],i)<=slope(Q[R-1],Q[R])) R--;
            Q[++R]=i;
        }
        printf("%lld
    ",f[n+1]);
        return 0;
    }
  • 相关阅读:
    [置顶] MySQL Cluster初步学习资料整理--安装部署新特性性能测试等
    ubuntu下设置开机自启动项
    【JSP】Cookie的使用及保存中文,并用Cookie实现购物车功能
    汉语-词语:笑面虎
    汉语-词语:阴险
    汉语-词语:奸猾
    汉语-词语:奸诈
    汉语-词语:厚道
    汉语-词语:忠厚
    汉语-词语:狡猾
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11505977.html
Copyright © 2011-2022 走看看