地址


注意思路!多看几遍!

很巧妙的一道题。不再是决策点以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[贪心+单调队列优化]的更多相关文章

  1. BZOJ1233 [Usaco2009Open]干草堆tower 【单调队列优化dp】

    题目链接 BZOJ1233 题解 有一个贪心策略:同样的干草集合,底长小的一定不比底长大的矮 设\(f[i]\)表示\(i...N\)形成的干草堆的最小底长,同时用\(g[i]\)记录此时的高度 那么 ...

  2. 【BZOJ 1233】 [Usaco2009Open]干草堆tower (单调队列优化DP)

    1233: [Usaco2009Open]干草堆tower Description 奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Bessie必须建一座干草堆使得她能够爬上去够到灯泡 .一共有N大包的 ...

  3. bzoj1233 [Usaco2009Open]干草堆tower 【单调队列dp】

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1233 单调队列优化的第一题,搞了好久啊,跟一开始入手斜率优化时感觉差不多... 这一题想通了 ...

  4. bzoj1233[Usaco2009Open]干草堆tower 单调队列优化dp

    1233: [Usaco2009Open]干草堆tower Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 983  Solved: 464[Submi ...

  5. bzoj1233: [Usaco2009Open]干草堆tower

    Description 奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Bessie必须建一座干草堆使得她能够爬上去够到灯泡 .一共有N大包的干草(1<=N<=100000)(从1到N编号) ...

  6. BZOJ1233 [Usaco2009Open]干草堆tower 和 BZOJ3549 [ONTAK2010]Tower

    题意 Problem 3549. -- [ONTAK2010]Tower 3549: [ONTAK2010]Tower Time Limit: 10 Sec  Memory Limit: 64 MBS ...

  7. bzoj 1233: [Usaco2009Open]干草堆tower

    1233: [Usaco2009Open]干草堆tower Description 奶牛们讨厌黑暗. 为了调整牛棚顶的电灯的亮度,Bessie必须建一座干草堆使得她能够爬上去够到灯泡 .一共有N大包的 ...

  8. USACO 2009 Open 干草塔 Tower of Hay(贪心+单调队列优化DP)

    https://ac.nowcoder.com/acm/contest/1072/B Description 为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉.干草包会从传送带上 ...

  9. bzoj 1233: [Usaco2009Open]干草堆tower 【想法题】

    首先这题的$n^3$的DP是比较好想的 $f[i][j]$表示用前$i$包干草 且最顶层为第$j+1$包到第$i$包 所能达到的最大高度 然而数据范围还是太大了 因此我们需要去想一想有没有什么单调性 ...

随机推荐

  1. JavaScript 基础入门11 - 运动框架的封装

    目录 JavaScript 运动原理 运动基础 简单运动的封装 淡入淡出 不同属性的设置 多属性值同时运动 运动回调,链式运动 缓冲运动 加入缓冲的运动框架 案例1 多图片展开收缩 运动的留言本 Ja ...

  2. redhat网卡设置

    在终端中输入:vi /etc/sysconfig/network-scripts/ifcfg-eth0   开始编辑,填写ip地址.子网掩码.网关.DNS等.其中“红框内的信息”是必须得有的.   编 ...

  3. MATLAB实现OTSU

    目录 1.OTSU算法原理简述: 2.MATLAB实现代码 @ 1.OTSU算法原理简述: 最大类间方差是由日本学者大津(Nobuyuki Otsu)于1979年提出,是一种自适应的阈值确定方法.算法 ...

  4. 【AMAD】django-model-utils -- Django model使用的mixin和utils

    动机 简介 个人评分 动机 为django model系统提供一些可重用的mixin和utils. 简介 django-model-utils1为Django Model提供了下嘛几种分类的utils ...

  5. 【Python开发】Lambda表达式使用

    lambda只是一个表达式,函数体比def简单很多. lambda的主体是一个表达式,而不是一个代码块.仅仅能在lambda表达式中封装有限的逻辑进去. lambda表达式是起到一个函数速写的作用.允 ...

  6. 2016年蓝桥杯省赛C++A组 消除尾一

    消除尾一: 下面的代码把一个整数的二进制表示的最右边的连续的1全部变成0如果最后一位是0,则原数字保持不变. 如果采用代码中的测试数据,应该输出: 00000000000000000000000001 ...

  7. C++多线程基础学习笔记(一)

    下面分三个方面多线程技术的必须掌握一些基本知识. 1.进程 2.线程 3.并发 (1)进程 一个可执行程序运行起来了,即为创建了一个进程.如在电脑上打开了word,就创建了一个word进程,打开QQ, ...

  8. # 「NOIP2010」关押罪犯(二分图染色+二分答案)

    「NOIP2010」关押罪犯(二分图染色+二分答案) 洛谷 P1525 描述:n个罪犯(1-N),两个罪犯之间的仇恨值为c,m对仇恨值,求怎么分配使得两件监狱的最大仇恨值最小. 思路:使最大xxx最小 ...

  9. mongodb 添加用户

    use admindb.createUser({ user:"admin", pwd:"abc123456", roles:[{role:"root& ...

  10. 关于ionic4导入android studio的注意事项

    最近看IT营的视频的时候,发现视频讲解的打包真是轻松的不得了,但是当自己导入打包的时候,你就会发现,没有最坑,只有更坑,按照教程来打包,估计你这辈子很难还原成功的,下面就来说一下关于 gradle与g ...