为了调整电灯亮度,贝西要用干草包堆出一座塔,然后爬到牛棚顶去把灯泡换掉。干草包会从传送带上运来,共会出现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. 二十九、利用 IntelliJ IDEA 进行代码对比的方法

    我们会有这样的需求,即:想对比出两个不同版本代码的区别.如何实现? 第 1 种:如果我们是从 SVN 检出的项目,并且想比较本地代码与从 SVN 检出时的代码相比都有那些区别,可以按如下步骤操作, 如 ...

  2. java使用jsp建立项目+视频

    项目下载:https://pan.baidu.com/s/1rfwrihd82zAmpt3r-mxIMw 视频+项目下载:https://pan.baidu.com/s/17Cm0wW-S9xiUy4 ...

  3. Swift_下标

    Swift_下标 点击查看源码 func testSubscripts() { //下标关键字subscript //array测试 struct TestArray { //内部数组 var arr ...

  4. HDU 5536--Chip Factory(暴力)

    Chip Factory Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)T ...

  5. svn出现目标计算机积极拒绝无法链接

    这是由于没有启动服务器端监控的原因,只需要执行以下代码即可 svnserve -d --listen-port 8000 -r /opt/svn

  6. 大数据学习--day10(继承-权限-super-final-多态-组合)

    继承-权限-super-final-多态-组合 权限修饰符     内容         public         protected         default(不写就是它)         ...

  7. Java学习笔记二十一:Java面向对象的三大特性之继承

    Java面向对象的三大特性之继承 一:继承的概念: 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方 ...

  8. QOS-交换机拥塞管理

    QOS-交换机拥塞管理 2018年7月7日 20:29 优先级映射: 根据信任的优先级,查找映射表,标记丢弃优先级和本地优先级 如果信任端口优先级,不同产品优先级标记方式可能不同,S3610处理过程如 ...

  9. POJ-3436:ACM Computer Factory (Dinic最大流)

    题目链接:http://poj.org/problem?id=3436 解题心得: 题目真的是超级复杂,但解出来就是一个网络流,建图稍显复杂.其实提炼出来就是一个工厂n个加工机器,每个机器有一个效率w ...

  10. sas的使用

    1.建表 /*************************************/ /* create the second input data set */ /*************** ...