为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉。干草包会从传送带上运来,共会出现N包干草,第i包干草的宽度是W i ,高度和长度统一为1。干草塔要从底层开始铺建。贝西会选择最先送来的若干包干草,堆在地上作为第一层,然后再把紧接着送来的几包干草包放在第二层, 再铺建第三层……重复这个过程, 一直到所有的干 草全部用完。每层的干草包必须紧靠在一起,不出现缝隙,而且为了建筑稳定,上层干草的宽度不能超过下层的宽度。 按顺序运来的干草包一定要都用上, 不能将其中几个干草包弃置不用。贝西的目标是建一座最高的塔,请你来帮助她完成这个任务吧。

输入格式

第一行:单个整数:\(N,1≤N≤100000\)第二行到\(N + 1\)行:第\(i + 1\)行有一个整数\(W_i,1 ≤ W_i ≤ 10000\)

输出格式

第一行:单个整数,表示可以建立的最高高度

样例输入

3

1

2

3

样例输出

2

题解

我们考虑贪心的做法。让我们看下面这张图



如图,一个小学生都明白的道理:对于一个三角形,对它进行等面积变换,为了使其越长,其形状必须越瘦。同理,在这道题中我们可以将干草堆抽象为三角形,为了让干草堆更高,我们只能让其更瘦。这里引用ZKW大佬的证明过程。

任意取出一个能使层数最高的方案,设有\(C_A\)层,把其中从下往上每一层最大的块编号记为\(A_i\);任取一个能使底边最短的方案,设有\(C_B\)层,把其中从下往上每一层最大的块编号记为\(B_i\)。显然\(A_1>=B_1,A*C_B<=B*C_B\),这说明至少存在一个k属于(1,\(C_B\)),满足\(A*k-1>=B*k-1且A*k<=B*k\)。也就是说,方案A第K层完全被方案B第K 层包含。构造一个新方案,第K层往上按方案 A,往下按方案B,两边都不要的块放中间当第K层。新方案的层数与A相同,而底边长度与B相同。证毕。

我们的第一种方案即从下往上处理每一层,当可以将当前层的最后一个干草堆放到当前层+1时我们就将其放上去,直到所有层都不满足条件为止。当然,不能只进行一次排布,因为当第h层向上移动后,第h-1层就有可能重新获得向上移动的机会。

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
inline char get(){
static char buf[3000],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,3000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
register char c=get();register int f=1,_=0;
while(c>'9' || c<'0')f=(c=='-')?-1:1,c=get();
while(c<='9' && c>='0')_=(_<<3)+(_<<1)+(c^48),c=get();
return _*f;
}
struct edge{
deque<int> u;
int w=0;
bool up=1;
}E[maxn];
int n;
int h;
void exchange(){
h=1;
while(true){
E[h].up=1;
while(E[h].up){
//cout<<h<<":";
if(E[h].w-E[h].u.back() >= E[h+1].w+E[h].u.back()){
E[h].w-=E[h].u.back();
E[h+1].w+=E[h].u.back();
E[h+1].u.push_front(E[h].u.back());
E[h].u.pop_back();
//cout<<E[h+1].u.front()<<endl;
}
else E[h].up=0;
}
h++;
if(E[h].w==0)break;
}
}
int main(){
//freopen("1.txt","r",stdin);
n=read();
for(register int i=1;i<=n;i++)E[1].u.push_back(read()),E[1].w+=E[1].u.back();
for(register int i=1;i<=500000;i++)exchange();
cout<<h;
return 0;
}

但是此时我们发现时间复杂度过大,虽然方案本身是正确的却依然因为时限问题而TLE。甚至在数据比较严苛的时候我们甚至无法通过这种方案获得最终答案。

此时只能考虑另外的思路。

这时我们选择枚举最底层的组成,设\(f[i]\)表示从\(n到i\)中最底层的宽度,则可知\(f[i]=min(sum[j-1到i])\)。由于上一层的宽度永远小于下一层的宽度,所以\(f[j]<=sum[j-1到i]\)

再观察一下,由于所有的干草堆要全部使用且对于第\(i-1\)个干草堆放在第\(h\)层时,第\(i\)个必然放在第\(h\)层或第\(h+1\)层,我们可以令\(sum[i]\)表示宽度的前缀和,而\(sum[i]\)是随i的增大而增大的,所以从\(i到n\)一旦发现一个符合条件的决策\(j\),便将其取出来更新\(f[i]\)。但是因为这样做的复杂度较大,仍不能通过所有数据。

再次分析,发现所有的决策的值(例如对于决策\(j\)值即为\(sum[j-1])由n\)往前都是单调递减的,也就是一个比一个优。因此决定性的因素则是他们的生效时间。

#include <bits/stdc++.h>
#define maxn 100009
using namespace std;
inline char get(){
static char buf[3000],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,3000,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
register char c=get();register int f=1,_=0;
while(c>'9' || c<'0')f=(c=='-')?-1:1,c=get();
while(c<='9' && c>='0')_=(_<<3)+(_<<1)+(c^48),c=get();
return _*f;
}
int num[maxn],dp[maxn],f[maxn],sum[maxn],w[maxn];
int n;
int main(){
//freopen("1.txt","r",stdin);
n=read();
for(register int i=1;i<=n;i++){
w[i]=read();
sum[i]=sum[i-1]+w[i];
}
num[1]=n+1;
int h=1,t=1;
for(register int i=n;i;i--){
while(h<t && f[num[h+1]]<=sum[num[h+1]-1]-sum[i-1]) ++h;
f[i]=sum[num[h]-1]-sum[i-1];
dp[i]=dp[num[h]]+1;
num[++t]=i;
while((t>h) && (f[num[t-1]]-sum[num[t-1]-1]+sum[num[t]-1]>f[num[t]]))t--,num[t]=num[t+1];
}
cout<<dp[1];
return 0;
}

[USACO09Open] Tower of Hay 干草塔的更多相关文章

  1. USACO 2009 Open 干草塔 Tower of Hay

    USACO 2009 Open 干草塔 Tower of Hay Description 为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉.干草 包会从传送带上运来,共会出现N包 ...

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

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

  3. 1682: [Usaco2005 Mar]Out of Hay 干草危机

    1682: [Usaco2005 Mar]Out of Hay 干草危机 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 391  Solved: 258[ ...

  4. bzoj1682[Usaco2005 Mar]Out of Hay 干草危机*

    bzoj1682[Usaco2005 Mar]Out of Hay 干草危机 题意: 给个图,每个节点都和1联通,奶牛要从1到每个节点(可以走回头路),希望经过的最长边最短. 题解: 求最小生成树即可 ...

  5. 【BZOJ】1682: [Usaco2005 Mar]Out of Hay 干草危机(kruskal)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1682 最小生成树裸题.. #include <cstdio> #include < ...

  6. BZOJ 1682: [Usaco2005 Mar]Out of Hay 干草危机

    Description 牛们干草要用完了!贝茜打算去勘查灾情. 有N(2≤N≤2000)个农场,M(≤M≤10000)条双向道路连接着它们,长度不超过10^9.每一个农场均与农场1连通.贝茜要走遍每一 ...

  7. [Usaco2005 Mar]Out of Hay 干草危机

    题目描述 Bessie 计划调查N (2 <= N <= 2,000)个农场的干草情况,它从1号农场出发.农场之间总共有M (1 <= M <= 10,000)条双向道路,所有 ...

  8. 【最小生成树】BZOJ1682[Usaco2005 Mar]-Out of Hay 干草危机

    ...最小生成树裸题,9月最后一天刷水刷水. #include<iostream> #include<cstdio> #include<algorithm> usi ...

  9. bzoj 1682: [Usaco2005 Mar]Out of Hay 干草危机【并查集+二分】

    二分答案,把边权小于mid的边的两端点都并起来,看最后是否只剩一个联通块 #include<iostream> #include<cstdio> using namespace ...

随机推荐

  1. Spring时间(Date)类型转换+自定义

    第一种方法:利用内置的 CustomDateEditor(不推荐,每个类都需要定义) 首先,在我们的 Controller 的 InitBinder 里面,注册 CustomEditor //首先初始 ...

  2. 【HDOJ 5726】GCD(RMQ+二分)

    Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). ...

  3. oracle编程300例-性能优化(一)

    1.在SELECT语句中避免使用“*” 2.尽可能减小记录行数 3.使用rowid高效删除重复记录 实例: delete from stu s where s.rowid>(select min ...

  4. Spring的入门学习笔记 (AOP概念及操作+AspectJ)

    AOP概念 1.aop:面向切面(方面)编程,扩展功能不通过源代码实现 2.采用横向抽取机制,取代了传统的纵向继承重复代码 AOP原理 假设现有 public class User{ //添加用户方法 ...

  5. The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.报该错误的一种原因。

    今天发现某个action返回404. HTTP Status 404 – Not Found Type Status Report Message /xxx.action Description Th ...

  6. 将图片绘制到画布上:imagecopy()

    <?php //1. 绘制图像资源(创建一个画布) $image = imagecreatetruecolor(500, 300); //2. 先分配一个绿色 $green = imagecol ...

  7. CentOS7 LNMP+phpmyadmin环境搭建(二、LNMP环境搭建)

    上一篇博客我们在虚拟机上安装了centos7,接下来,就开始安装lnmp环境吧. 还是跟之前一样,进入命令行后,先使用su命令切换到root权限. 首先配置防火墙  CentOS 7.0默认使用的是f ...

  8. 我的名字叫hadoop

      第一回 新入环境 我的名字是hadoop,我一出生我的爸爸雅虎就给我取了这样一个名字:hadoop,我也不知道为什么叫这个名字,刚出生没多久,雅虎爸爸就把我领进一个黑暗的屋子里面,屋里堆满了黑色的 ...

  9. 全志A64 QT移植

    1. 把编译工具 gcc-linaro-aarch64.tar.xz 添加到环境.bashrc 中 2. 下载 tslib-1.4.tar.gz ,libiconv-1.15.tar.gz ,qt-e ...

  10. python中的__all__

    在定义一个模块的时候,在开头处加上 “ __all__ = ["xxx1", "xxx2"] ”(xxx可以是方法.类.变量等希望让外界访问的值),那么在外部通 ...