zoukankan      html  css  js  c++  java
  • [BZOJ3156]防御准备

        题目大意:
            给你$n$个格子,每个格子可以放一个人或建筑,
            放一个建筑的代价为$a_i$,放一个人的代价为这个格子与右边第一个有建筑的格子的距离,
            要求每个格子上都得放一个东西,
            问最小代价。
        思路:
            根据题意,我们可以列出状态转移方程$f_i=displaystyle{min_{j<i}}{f_j+displaystyle{sum_{k=j+1}^{i}}(i-k)}+a_i$。
            其中$displaystyle{sum_{k=j+1}^{i}}(i-k)$可以高斯求和。
            接下来考虑两个状态$j$和$k$,
            如果j比k优,那么一定有$f_j+frac{(i-j-1) imes(i-j)}{2}<f_k+frac{(i-k-1) imes(i-k)}{2}$。
            整理得$f_j-f_k+frac{j^2+j}{2}-frac{k^2+k}{2}<i(j-k)$。
            化为斜率式,就变成了$frac{f_j-f_k+frac{j^2+j}{2}-frac{k^2+k}{2}}{j-k}<i$。
            然后用单调队列维护下凸包,然后就WA了。
            发现实际上$j<k$,据说移到左边要变号?(初一学的全还给老师了)
            所以实际上应该$frac{f_j-f_k+frac{j^2+j}{2}-frac{k^2+k}{2}}{j-k}>i$。

     1 #include<cstdio>
     2 #include<cctype>
     3 inline int getint() {
     4     register char ch;
     5     while(!isdigit(ch=getchar()));
     6     register int x=ch^'0';
     7     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     8     return x;
     9 }
    10 typedef long long int64;
    11 const int N=1e6+1;
    12 int q[N],h,t;
    13 int64 f[N];
    14 inline double slope(const int64 &j,const int64 &k) {
    15     return (f[j]+(j*j+j)/2-f[k]-(k*k+k)/2)/(double)(j-k);
    16 }
    17 int main() {
    18     int n=getint();
    19     for(register int i=1;i<=n;i++) {
    20         int a=getint();
    21         while(h<t&&slope(q[h],q[h+1])<i) h++;
    22         f[i]=f[q[h]]+(int64)(i-q[h]-1)*(i-q[h])/2+a;
    23         while(h<t&&slope(q[t-1],q[t])>slope(q[t],i)) t--;
    24         q[++t]=i;
    25     }
    26     printf("%lld
    ",f[n]);
    27     return 0;
    28 }
  • 相关阅读:
    大话设计模式读书笔记--4.代理模式
    大话设计模式读书笔记--3.装饰模式
    大话设计模式读书笔记--2.策略模式
    大话设计模式读书笔记--1.简单工厂模式
    redis分片
    redis主从同步
    用Jedis连接Redis
    redis的数据类型和指令
    使用可视化工具redisclient连接redis
    《深入浅出通信原理》参考资料
  • 原文地址:https://www.cnblogs.com/skylee03/p/7619722.html
Copyright © 2011-2022 走看看