zoukankan      html  css  js  c++  java
  • 单调栈 BZOJ2364 城市美化

    2364: 城市美化

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 182  Solved: 42
    [Submit][Status][Discuss]

    Description

    城市A需要美化市容市貌,现在有n个楼房排成一列,每个楼房的高都在[1,1000]的范围内。市长请了一批工程师来对其中一些楼房进行修建,使楼房高度得到上升(不能让楼房高度下降),对一栋楼房修建,使其高度上升x,需要x2的费用。
    当所有修建完成后,我们把相邻两楼高度的绝对值乘以c(0<=c<=1000),得到的就是城市损失的钱,我们把它同样看作是费用。现在想请你合理安排修建楼房的方案,使得所需费用最小。
     

    Input

    第一行两个数n和c。
    接下来n行,每行一个数,表示每栋楼的高度。
     

    Output

    仅一行一个数,表示最小所需的费用。

    Sample Input

    5 5
    2
    2
    1
    6
    8

    Sample Output

    31

    HINT

    数据范围

    对于100%的数据,1<=n<=50000

    f[i]表示前i个且最后一段与 i-1 相同的最小代价。

    可以得到一些性质:(1) 当一个楼房两边都比它高,或者一个楼房处于边界,那么将它向上调整才能使代价减小;

             (2) 若一个楼房两边都高于它,且最后它向上调整了,则两侧的楼房高度都应与它相同,直到有比它更高的为止。

    则可以维护一个单调递减的楼房转移,ask用于二次函数求极值。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 int n,c,top;
     8 int stack[50010];
     9 long long h[50010],sum[50010],sumpow[50010],f[50010];
    10 long long ask(long long a,long long b,long long d,long long mn,long long mx){
    11     double t=(double)-b/(2*a);
    12     long long x;
    13     if(mn<=t&&t<=mx) x=round(t);
    14     if(mn>t) x=mn;
    15     if(mx<t) x=mx;
    16     return a*x*x+b*x+d; 
    17 }
    18 long long solve(int ll,int rr,long long mn){
    19     if(ll+1==rr) return (ll==1||rr==n+2)?0:abs(h[rr]-h[ll])*c;
    20     long long a=rr-ll-1,b=-2*(sum[rr-1]-sum[ll]),d=sumpow[rr-1]-sumpow[ll];
    21     long long mx=min(h[ll],h[rr]);
    22     if(ll!=1) b-=c,d+=c*h[ll];
    23     if(rr!=n+2) b-=c,d+=c*h[rr];
    24     return ask(a,b,d,mn,mx);
    25 }
    26 long long work(){
    27     stack[++top]=1;
    28     for(int i=2;i<=n+2;i++){
    29         f[i]=1e60;
    30         int end=0;
    31         while(top&&h[stack[top]]<h[i]){
    32             f[i]=min(f[i],f[stack[top]]+solve(stack[top],i,end));
    33             end=h[stack[top--]];
    34         }
    35         f[i]=min(f[i],f[stack[top]]+solve(stack[top],i,end));
    36         stack[++top]=i;
    37     } 
    38     return f[n+2];
    39 }
    40 int main(){
    41     scanf("%d%d",&n,&c);
    42     h[1]=h[n+2]=1e60;
    43     for(int i=1;i<=n;i++) scanf("%d",&h[i+1]);
    44     for(int i=1;i<=n+2;i++){
    45         sum[i]=sum[i-1]+h[i];
    46         sumpow[i]=sumpow[i-1]+h[i]*h[i];
    47     }
    48     printf("%lld",work());
    49     return 0;
    50 }
  • 相关阅读:
    atitit.TokenService v3 qb1 token服务模块的设计 新特性.docx
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    atitit。企业的价值观 员工第一 vs 客户第一.docx
    Atitit 实现java的linq 以及与stream api的比较
    Atitit dsl exer v3 qb3 新特性
    Atititi tesseract使用总结
    Atitit 修改密码的功能流程设计 attilax总结
    atitit.TokenService v3 qb1  token服务模块的设计 新特性.docx
  • 原文地址:https://www.cnblogs.com/zwube/p/7259818.html
Copyright © 2011-2022 走看看