题目描述





分析

  • 对于 \(Subtask\ 1\),可以写一个 \(n^3\) 的 \(DP\),\(f[i][j]\) 代表第 \(i\) 个建筑高度为 \(j\) 时的最小花费,随便转移即可

    时间复杂度 \(O(n \times h^2)\)
  • 对于 \(Subtask\ 2\),我们沿用 \(Subtask\ 1\)的思路,记录前缀后缀 \(min\),将复杂度优化至 \(O(n \times h)\)

    但是显然两维的定义无法继续进行优化,我们可以考虑改变一下定义的方式

    设 \(f[i]\) 表示考虑前 \(i\) 个建筑,并且第 \(i\) 个建筑高度不变的最优答案

    可以发现,枚举两个不变的边界,那么中间的建筑必定被提高成相同的小于等于边界的高度

    也就是说我们需要把一些坑填平

    因为增加峰的高度既花人力又不能提高观赏度

    增加坡的高度花人力但不能提高观赏度

    只有增加坑的高度才会有贡献,而且增加的值不能超过边界的高度

    因为超过边界的高度又变成了峰

    因此我们可以枚举边界然后再枚举填平的高度

    转移方程为 \(f[i]=f[j]+(sum2[i-1]-sum2[j])+(i-j-1)*h*h-(sum1[i-1]-sum1[j])*2*h+c*abs(a[i]+a[j]-2*h)\)

    其中 \(sum1[i]\) 为 \(a\) 数组的前缀和,\(sum2[i]\) 为 \(a\) 数组平方的前缀和

    上面的式子是展开后的式子,原式子并不难推

    注意这种做法我们需要把 \(a[0]\) 和 \(a[n+1]\) 置为无穷大,因为我们有可能提高第一个和最后一个建筑的高度

    要特判 \(i,j\) 等于 \(0\)或 \(n+1\) 的情况

    最后的答案为 \(f[n+1]\)

    时间复杂度 \(O(n^2 \times h)\),不知道为什么能过这个子任务
  • 对于 \(Subtask\ 3\),我们把一维 \(DP\) 的状态转移方程化简得到

    \(f[i]=f[j]+(i-j-1)*h*h-2*(sum1[i-1]-sum1[j]+c)*h+(sum2[i-1]-sum2[j])+c*(a[i]+a[j])\)

    我们发现前半部分是一个关于高度 \(h\) 的二次函数

    可以直接由对称轴求出最小值

    时间复杂度 \(O(n^2)\)
  • 对于 \(Subtask\ 4\) 和 \(Subtask\ 5\),我们会发现只有两个高度较大的建筑夹着一堆高度较小的建筑才有贡献

    因此可以用单调队列(栈)维护

    时间复杂度 \(O(n logn)\)

    复杂度的瓶颈在\(ST\) 表查询最值上

代码

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
#define rg register
inline int read(){
rg int x=0,fh=1;
rg char ch=getchar();
while(ch<'0' || ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*fh;
}
typedef long long ll;
const int maxn=1e6+5;
int n,c,a[maxn],maxh,lg[maxn],st[maxn][22],head,tail,q[maxn];
ll f[maxn],sum1[maxn],sum2[maxn];
int zhao(ll i,ll j){
if(j==0 && i==n+1) return ((double)(sum1[i-1]-sum1[j])/(double)(i-j-1)+0.5);
else if(j==0 || i==n+1) return ((double)(2*sum1[i-1]-2*sum1[j]+c)/(double)(2.0*(i-j-1))+0.5);
return ((double)(c+sum1[i-1]-sum1[j])/(double)(i-j-1)+0.5);
}
int cx(int l,int r){
rg int k=lg[r-l+1];
return std::max(st[l][k],st[r-(1<<k)+1][k]);
}
int main(){
memset(f,0x3f,sizeof(f));
n=read(),c=read();
for(rg int i=1;i<=n;i++){
a[i]=read();
maxh=std::max(maxh,a[i]);
sum1[i]=sum1[i-1]+a[i];
sum2[i]=sum2[i-1]+1LL*a[i]*a[i];
st[i][0]=a[i];
}
for(rg int i=2;i<=n;i++){
lg[i]=lg[i/2]+1;
}
for(rg int j=1;j<=20;j++){
for(rg int i=1;i+(1<<j)-1<=n;i++){
st[i][j]=std::max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
a[0]=a[n+1]=0x3f3f3f3f;
f[0]=f[1]=0;
head=1,tail=1;
rg int mmax,mmin,now;
for(rg int i=1;i<=n+1;i++){
while(head<=tail){
if(q[tail]==i-1){
if(i<=n) f[i]=std::min(f[i],f[q[tail]]+1LL*c*std::abs(a[i]-a[i-1]));
else f[i]=f[i-1];
} else {
mmax=cx(q[tail]+1,i-1);
mmin=std::min(a[i],a[q[tail]]);
if(mmin>=mmax){
now=zhao(i,q[tail]);
if(now<mmax) now=mmax;
if(now>mmin) now=mmin;
if(q[tail]==0 && i==n+1) f[i]=std::min(f[i],f[q[tail]]+1LL*(i-q[tail]-1)*now*now-2LL*(sum1[i-1]-sum1[q[tail]])*now+1LL*(sum2[i-1]-sum2[q[tail]]));
else if(q[tail]==0) f[i]=std::min(f[i],f[q[tail]]+1LL*(i-q[tail]-1)*now*now-1LL*(2*sum1[i-1]-2*sum1[q[tail]]+c)*now+1LL*(sum2[i-1]-sum2[q[tail]])+1LL*c*a[i]);
else if(i==n+1) f[i]=std::min(f[i],f[q[tail]]+1LL*(i-q[tail]-1)*now*now-1LL*(2*sum1[i-1]-2*sum1[q[tail]]+c)*now+1LL*(sum2[i-1]-sum2[q[tail]])+1LL*c*a[q[tail]]);
else f[i]=std::min(f[i],f[q[tail]]+1LL*(i-q[tail]-1)*now*now-2LL*(sum1[i-1]-sum1[q[tail]]+c)*now+1LL*(sum2[i-1]-sum2[q[tail]])+1LL*c*(a[i]+a[q[tail]]));
}
}
if(a[i]>=a[q[tail]])tail--;
else break;
}
q[++tail]=i;
}
printf("%lld\n",f[n+1]);
return 0;
}

联赛模拟测试18 A. 施工 单调队列(栈)优化DP的更多相关文章

  1. 单调队列 && 斜率优化dp 专题

    首先得讲一下单调队列,顾名思义,单调队列就是队列中的每个元素具有单调性,如果是单调递增队列,那么每个元素都是单调递增的,反正,亦然. 那么如何对单调队列进行操作呢? 是这样的:对于单调队列而言,队首和 ...

  2. 洛谷P1725 琪露诺 (单调队列/堆优化DP)

    显然的DP题..... 对于位置i,它由i-r~i-l的位置转移过来,容易得到方程 dp[i]=dp[i]+max(dp[i−r],...,dp[i−l]). 第一种:n2的暴力,只能拿部分分. 1 ...

  3. HDU 3507 单调队列 斜率优化

    斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...

  4. csp-s模拟测试50(9.22)「施工(单调栈优化DP)」·「蔬菜(二维莫队???)」·「联盟(树上直径)」

    改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调 ...

  5. 【P2422】良好的感觉(单调栈优化DP//奇怪的暴力)

    话说正解是单调栈优化DP,然而貌似根据某种玄学的推算,这个题暴力出解貌似也是可以的.首先,我们枚举所有的点作为最小点,然后横向展开,遇到更小的就停止...然后再操作一下,看上去时间O(N^2),然而由 ...

  6. 【BZOJ-2892&1171】强袭作战&大sz的游戏 权值线段树+单调队列+标记永久化+DP

    2892: 强袭作战 Time Limit: 50 Sec  Memory Limit: 512 MBSubmit: 45  Solved: 30[Submit][Status][Discuss] D ...

  7. luogu 2216 理想的正方形 单调队列(其实没有DP)

    #include<bits/stdc++.h> using namespace std; ; ; int a,b,n; int g[A][A],q[A][N],Q[A][N]; int h ...

  8. 洛谷 P2254 [NOI2005]瑰丽华尔兹(单调栈优化DP)

    题目描述 不妨认为舞厅是一个N行M列的矩阵,矩阵中的某些方格上堆放了一些家具,其他的则是空地.钢琴可以在空地上滑动,但不能撞上家具或滑出舞厅,否则会损坏钢琴和家具,引来难缠的船长.每个时刻,钢琴都会随 ...

  9. 联赛模拟测试24 D. 你相信引力吗 单调栈

    题目描述 分析 因为跨过最大值的区间一定是合法的,所以我们人为地把最大值放在最左边 我们要统计的就是在最大值右边单调不降的序列,可以用单调栈维护 需要特殊处理相同的情况 代码 #include< ...

随机推荐

  1. 2020BJDCTF

    diff: 不得不说这种题目挺有意思的,现在记录一下阶梯过程: 先登录远程,发现有两个文件: 虽然直接能卡到flag文件,但是我们是以ctf用户登录的,并不能直接打开flag文件.仔细观察diff文件 ...

  2. 吴恩达《深度学习》-第五门课 序列模型(Sequence Models)-第三周 序列模型和注意力机制(Sequence models & Attention mechanism)-课程笔记

    第三周 序列模型和注意力机制(Sequence models & Attention mechanism) 3.1 序列结构的各种序列(Various sequence to sequence ...

  3. 利用 QEMU USER 模式运行 mips 程序

    摘要 关键字: qemu mips 前述 QEMU是一个处理器模拟软件,可以用来在PC中模拟ARM.MIPS等多种架构的软硬件运行环境.QEMU主要有两种模拟模式: User Mode System模 ...

  4. axios post提交数据的三种请求方式

    1.Content-Type: application/json import axios from 'axios' let data = {"code":"1234&q ...

  5. Win10安装Tensorflow-gpu遇到Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问

    最近因为上课需要安装Anaconda和Tensorflow,安装Anaconda后再使用 Tensorflow官网提供的pip安装Tensorflow-GPU方法会出现如下错误: 解决方法:在安装命令 ...

  6. Spring Cloud Alibaba微服务生态的基础实践

    目录 一.背景 二.初识Spring Cloud Alibaba 三.Nacos的基础实践 3.1 安装Nacos并启动服务 3.2 建立微服务并向Nacos注册服务 3.3 建立微服务消费者进行服务 ...

  7. 分布式系统监视zabbix讲解五之web监控

    Web 监控 概况 你可以使用 Zabbix 检查几个网站可用性方面. 如果要使用 Web 检测功能,必须在 编译Zabbix 的时候加入 cURL(libcurl) 的支持. 要使用 Web 监控, ...

  8. python中RGB色彩

    turtle.colormode(mode)来改变色彩数值的使用 如果在修改颜色时写turtle.colormode(1.0) ,就需要使用RGB小数模式来去改变颜色 如果在修改颜色时写turtle. ...

  9. Infor EAM:注重行业属性,实现对轨道交通线性资产的可视化管理

    Infor EAM:注重行业属性,实现对轨道交通线性资产的可视化管理 企业得利,一要开源,二要节流.而企业资产管理的目的,也正是从资产的角度出发,一方面通过相关资源与活动的合理安排提高设备可利用率.增 ...

  10. springboot之logback配置

    参考了https://blog.csdn.net/hxtxgfzs/article/details/79488163 Spring Boot默认情况下,当使用"Starters" ...