【USACO 2009 OPen】干草塔

Description

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

Input

第一行:单个整数:N,1 ≤ N ≤ 100000
第二行到N + 1行:第i + 1行有一个整数Wi,1 ≤ Wi≤ 10000

Output

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

Sample Input

3

1 2 3

Sample Output

2

Hint

(将 1 和 2 放在第一层,将 3 放在第二层)

首先肯定想到贪心,但是随手被卡:7 6 2 4,但我们可以感性理解到每一层肯定是越窄越好,所以可以设计出f[i]表示后i个的最窄的宽度,显然f[i]是单调不下降的,于是可以用单调队列优化。

#include
using namespace std;
const int Maxn=100005;
int n,a[Maxn],s[Maxn],f[Maxn];
int l,r,q[Maxn];
//if(f[j]<=s[i]-s[j])f[i]=min(f[i],s[i]-s[j]);
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		scanf("%d",&a[i]);
	for(int i=1;i<=n/2;++i)swap(a[i],a[n-i+1]);
	for(int i=1;i<=n;++i)s[i]=s[i-1]+a[i];
	f[q[l=r=1]=0]=0;
	for(int i=1;i<=n;++i){
		while(l=1;--i){
		wide-=a[i];
		if(wide==0)++high,wide=f[i-1];
	}
	cout<

 

你可能感兴趣的:(单调队列优化dp,动态规划)