BZOJ1233 [Usaco2009Open]干草堆tower[贪心+单调队列优化]
注意思路!多看几遍!
很巧妙的一道题。不再是决策点以dp值中一部分含j项为维护对象,而是通过维护条件来获取决策。
首先有个贪心策略,让底层的宽度尽可能小,才能让高度尽可能高。所以应该倒着dp,表示堆$i$~$n$的最高高度$f[i]$,同时这种最值应来源于之后的j,要在设一个$g[i]$表示以i为底层,最窄的宽度。这个的话真的只可意会啊。注意$g[i]$没人告诉你是单调的,$g[i]$之后一个不合法的决策都可能有$g[j]>g[i]$,所以单调性问题还当谨慎考虑。
所以dp方程就能出来了
$g[i]=min(sum[j-1]-sum[i-1]) $ $ g[j]<=sum[j-1]-sum[i-1]$
$f[i]=f[j]+1$
然后这个是$O(n^2)$的,考虑优化。从min内可以看出,j越小越好。那瓶颈就在于后面的那个约束条件怎么用,就是我在保证条件的情况下取j最小。
转化条件:$g[j]<=sum[j-1]-sum[i-1]$移项得$sum[j-1]-g[j]≥sum[i-1]$,而$sum[i-1]$是单调减的,那我要之前的j得插入$sum[j-1]-g[j]$,在dp到i时去把决策中大于等于$sum[i-1]$的找一个最小j。
于是单调队列维护j单调递减,$sum[j-1]-g[j]$单调减元素。假设dp完i后,我将目前i要向单调队列队尾比较。如果$sum[j-1]-g[j]>=sum[q[r]-1]-g[q[r]]$也就是j可以发挥与队尾同等的作用(甚至更优)的话,而我又渴求j尽可能小,那队尾就没什么卵用可以弹出了。直到不满足上述比较,就在队尾插入。这样保证$sum[j-1]-g[j]$单调减,我要取合法决策,便是队列头开始的一段大于等于$sum_i$的。注意,我要j最小,那队头满足条件的若干个决策,只要j最小的,那我可以依据j单调性将队头不断pop(反正之后$sum[i-1]$只会更小,现在留着也没用),直到最后一个满足条件的,就是最小的j。还是有点难以理解,贴个图。

然后每次就可以取到最小满足条件j了。
这个故事告诉我们单调队列的队头并不就一定是检查队头合法性的(范围之类的),也可以排除不优决策,这依赖于队头和队头下一个元素间的相互比较,要结合单调性予以考虑。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+;
int sum[N],f[N],g[N],q[N];
int n,l,r; int main(){//freopen("test.in","r",stdin);//freopen("tmp.out","w",stdout);
read(n);for(register int i=;i<=n;++i)sum[i]=read(sum[i])+sum[i-];
l=,r=;q[l]=n+;
for(register int i=n;i;--i){
while(l<r&&sum[q[l+]-]-g[q[l+]]>=sum[i-])++l;
g[i]=sum[q[l]-]-sum[i-],f[i]=f[q[l]]+;
while(l<=r&&sum[q[r]-]-g[q[r]]<=sum[i-]-g[i])--r;
q[++r]=i;
}
printf("%d\n",f[]);
return ;
}
BZOJ1233 [Usaco2009Open]干草堆tower[贪心+单调队列优化]的更多相关文章
- BZOJ1233 [Usaco2009Open]干草堆tower 【单调队列优化dp】
题目链接 BZOJ1233 题解 有一个贪心策略:同样的干草集合,底长小的一定不比底长大的矮 设\(f[i]\)表示\(i...N\)形成的干草堆的最小底长,同时用\(g[i]\)记录此时的高度 那么 ...
- 【BZOJ 1233】 [Usaco2009Open]干草堆tower (单调队列优化DP)
1233: [Usaco2009Open]干草堆tower Description 奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Bessie必须建一座干草堆使得她能够爬上去够到灯泡 .一共有N大包的 ...
- bzoj1233 [Usaco2009Open]干草堆tower 【单调队列dp】
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1233 单调队列优化的第一题,搞了好久啊,跟一开始入手斜率优化时感觉差不多... 这一题想通了 ...
- bzoj1233[Usaco2009Open]干草堆tower 单调队列优化dp
1233: [Usaco2009Open]干草堆tower Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 983 Solved: 464[Submi ...
- bzoj1233: [Usaco2009Open]干草堆tower
Description 奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Bessie必须建一座干草堆使得她能够爬上去够到灯泡 .一共有N大包的干草(1<=N<=100000)(从1到N编号) ...
- BZOJ1233 [Usaco2009Open]干草堆tower 和 BZOJ3549 [ONTAK2010]Tower
题意 Problem 3549. -- [ONTAK2010]Tower 3549: [ONTAK2010]Tower Time Limit: 10 Sec Memory Limit: 64 MBS ...
- bzoj 1233: [Usaco2009Open]干草堆tower
1233: [Usaco2009Open]干草堆tower Description 奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Bessie必须建一座干草堆使得她能够爬上去够到灯泡 .一共有N大包的 ...
- USACO 2009 Open 干草塔 Tower of Hay(贪心+单调队列优化DP)
https://ac.nowcoder.com/acm/contest/1072/B Description 为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉.干草包会从传送带上 ...
- bzoj 1233: [Usaco2009Open]干草堆tower 【想法题】
首先这题的$n^3$的DP是比较好想的 $f[i][j]$表示用前$i$包干草 且最顶层为第$j+1$包到第$i$包 所能达到的最大高度 然而数据范围还是太大了 因此我们需要去想一想有没有什么单调性 ...
随机推荐
- PHP curl出现SSL certificate problem: self signed certificate in certificate chain
使用PHP curl请求https的时候出现错误“SSL certificate problem: self signed certificate in certificate chain”,这种情况 ...
- PI膜概述
一.概述 1.简述 聚酞亚胺薄膜又称PI薄膜(polyimide filin)是一种含有酞亚胺或丁二酞亚胺的绝缘类高分子材料.是目前工程塑料中耐热性最好的品种之一. 2.发展简史 1908年,PI聚合 ...
- 【JulyEdu-Python基础】第 4 课:面向对象基础
类(class):用来描述具有相同的属性和方法的对象的集合,它定义了该集合中每个对象所共有的属性和方法.对象是类的实例. 对象:通过类定义的数据结构实例.对象包括两个数据成员(类变量和实例变量)和方法 ...
- Leetcode之动态规划(DP)专题-931. 下降路径最小和(Minimum Falling Path Sum)
Leetcode之动态规划(DP)专题-931. 下降路径最小和(Minimum Falling Path Sum) 给定一个方形整数数组 A,我们想要得到通过 A 的下降路径的最小和. 下降路径可以 ...
- 华为HCNA乱学Round 12:NAT和easy IP
- Java架构师 成长之路 -- 跳出程序员陷阱(转载)
本人也是coding很多年,虽然很失败,但也总算有点失败的心得,不过我在中国,大多数程序员都是像我一样,在一直走着弯路. 如果想成为一个架构师,就必须走正确的路,否则离目标越来越远,正在辛苦工作的程序 ...
- JDBC基本操作
前言:什么是JDBC 维基百科的简介: Java 数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提 ...
- [转帖]从Intel和ARM争霸,谈芯片前世今生
从Intel和ARM争霸,谈芯片前世今生 http://www.itpub.net/2019/07/24/2476/ 长文预警, 写的非常好.. 我尽量写得轻松一些,因为其实这个话题很有趣,仔细探究起 ...
- 用Python快速找到出现次数最多的数据
给你一个文件,每行一个iip?
- Ubuntu 系统安装 Docker
安装 Docker CE 有多种方法,下面是最简单的通过Docker仓库的安装方法,其他方法参见官方文档. 设置仓库 刷新软件包 sudo apt-get update 安装必要的软件包 sudo a ...