当农夫约翰闲的没事干的时候,他喜欢坐下来看书。多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书。

每本书 i 都有宽度 W(i) 和高度 H(i)。书需要按顺序添加到一组书架上;比如说,第一层架子应该包含书籍1 ... k,第二层架子应该以第k + 1本书开始,以下如此。每层架子的总宽度最大为L(1≤L≤1,000,000,000)。每层的高度等于该层上最高的书的高度,并且整个书架的高度是所有层的高度的总和,因为它们都垂直堆叠。

请帮助农夫约翰计算整个书架的最小可能高度。

有N(1 <= N <= 100000)本书,每本书有一个宽度W(i),高度H(i),(1 <= H(i) <= 1,000,000; 1 <= W(i) <= L)。

现在有足够多的书架,书架宽度最多是L (1 <= L <= 1,000,000,000),把书按顺序(先放1,再放2.....)放入书架。某个书架的高度是该书架中所放的最高的书的高度。

将所有书放入书架后,求所有书架的高度和的最小值?

Solution

一眼dp优化。

状态方程显然,dp[[i]=dp[j]+maxh(j~i).然后用线段树优化,区间取max,单点修改。

但答案是两部分构成的,区间取max会炸。。

于是我想了一晚上。。。

我们发现每次取max会改变一段连续的区间,所以我们维护一个单调递减的队列,每次找到前面第一个比它大的点,直接区间修改就可以了。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 100002
using namespace std;
typedef long long ll;
long long tr[N<<],sum[N],w[N],m,n,h[N],x,q[N],la[N<<],ans[N<<];
inline void pushdown(int cnt){
la[cnt<<]=la[cnt<<|]=la[cnt];la[cnt]=;
ans[cnt<<]=tr[cnt<<]+la[cnt<<];ans[cnt<<|]=tr[cnt<<|]+la[cnt<<|];
}
void add(int cnt,int l,int r,int x,ll y){
if(l==r){
tr[cnt]=y;
ans[cnt]=y+la[cnt];
return;
}
int mid=(l+r)>>;
if(la[cnt])pushdown(cnt);
if(mid>=x)add(cnt<<,l,mid,x,y);
else add(cnt<<|,mid+,r,x,y);
tr[cnt]=min(tr[cnt<<],tr[cnt<<|]);
ans[cnt]=min(ans[cnt<<],ans[cnt<<|]);
}
ll query(int cnt,int l,int r,int L,int R){
if(l>=L&&r<=R)return ans[cnt];
int mid=(l+r)>>;
ll ans=1e18;
if(la[cnt])pushdown(cnt);
if(mid>=L)ans=min(ans,query(cnt<<,l,mid,L,R));
if(mid<R)ans=min(ans,query(cnt<<|,mid+,r,L,R));
return ans;
}
void upd(int cnt,int l,int r,int L,int R,ll x){
if(L>R)return;
if(l>=L&&r<=R){
la[cnt]=x;
ans[cnt]=tr[cnt]+la[cnt];
return;
}
int mid=(l+r)>>;
if(la[cnt])pushdown(cnt);
if(mid>=L)upd(cnt<<,l,mid,L,R,x);
if(mid<R)upd(cnt<<|,mid+,r,L,R,x);
tr[cnt]=min(tr[cnt<<],tr[cnt<<|]);
ans[cnt]=min(ans[cnt<<],ans[cnt<<|]);
}
int find(int x){
int l=,r=x,ans;
while(l<=r){
int mid=(l+r)>>;
if(sum[x]-sum[mid]<=m){
ans=mid;
r=mid-;
}
else l=mid+;
}
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
memset(tr,0x3f,sizeof(tr));memset(ans,0x3f,sizeof(ans));
for(int i=;i<=n;++i)scanf("%lld%lld",&h[i],&w[i]),sum[i]=sum[i-]+w[i];
int mn=;
add(,,n,,);
int hh,t;
hh=t=;q[hh]=;
for(int i=;i<=n;++i){
while(hh<=t&&h[q[t]]<h[i])t--;
upd(,,n,hh<=t?q[t]:,i-,h[i]);
q[++t]=i;
x=query(,,n,find(i),i-);
add(,,n,i,x);
}
printf("%lld",x);
return ;
}

TJOI2011书架(dp)的更多相关文章

  1. P1295 [TJOI2011]书架 线段树优化dp,单调栈

    P1295 [TJOI2011]书架 本题思路比较好想(对我来说不是),但代码细节很多,奈何洛谷的题解只有思路,然后就是 没有丝毫解释的代码,让人看起来很头疼(~~ 尤其是像我这样的蒟蒻~~),所以便 ...

  2. BZOJ5125: [Lydsy1712月赛]小Q的书架【决策单调性优化DP】【BIT】【莫队】【分治】

    小Q有n本书,每本书有一个独一无二的编号,现在它们正零乱地在地上排成了一排. 小Q希望把这一排书分成恰好k段,使得每段至少有一本书,然后把每段按照现在的顺序依次放到k层书架的每一层上去.将所有书都放到 ...

  3. Codeforces 981 共同点路径覆盖树构造 BFS/DP书架&最大值

    A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...

  4. [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)

    显然有决策单调性,但由于逆序对不容易计算,考虑分治DP. solve(k,x,y,l,r)表示当前需要选k段,待更新的位置为[l,r],这些位置的可能决策点区间为[x,y].暴力计算出(l+r)/2的 ...

  5. BZOJ5125: [Lydsy1712月赛]小Q的书架(DP决策单调性)

    题意:N个数,按顺序划分为K组,使得逆序对之和最小. 思路:之前能用四边形不等式写的,一般网上都还有DP单调性分治的做法,今天也尝试用后者写(抄)了一遍.即: 分成K组,我们进行K-1次分治,get( ...

  6. [Luogu1848][USACO12OPEN]书架Bookshelf DP+set+决策单调性

    题目链接:https://www.luogu.org/problem/show?pid=1848 题目要求书必须按顺序放,其实就是要求是连续的一段.于是就有DP方程$$f[i]=min\{f[j]+m ...

  7. LightOJ1283 Shelving Books(DP)

    题目 Source http://www.lightoj.com/volume_showproblem.php?problem=1283 Description You are a librarian ...

  8. [USACO12OPEN]书架Bookshelf

    Description 当农夫约翰闲的没事干的时候,他喜欢坐下来看书.多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书. 每本书 i ...

  9. DP擎天

    DP! 黄题: 洛谷P2101 命运石之门的选择 假装是DP(分治 + ST表) CF 982C Cut 'em all! 树形贪心 洛谷P1020 导弹拦截 单调队列水题 绿题: 洛谷P1594 护 ...

随机推荐

  1. ssm项目跨域访问

    最近使用ssm开发了一个项目,为了项目的开发速度,采用的是前后端同时开发,所以前端文件没有集成在项目中,最后在调试时涉及到了跨域.跨域的解决方法很多,我采用的是最简单的一种,代码如下: 新建一个过滤器 ...

  2. 《Effective C++》让自己习惯C++:条款1-条款4

    条款1:视C++为一个语言联邦 可以将C++分为4个层次: 1.C:C++实在C语言的基础上发展而来的. 2:Object-Oriented C++:C++面向对象. 3:Template C++:C ...

  3. HDU 4913 Least common multiple

    题目:Least common multiple 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4913 题意:有一个集合s,包含x1,x2,...,xn, ...

  4. 关于手机端适配的问题(rem,页面缩放)

    关于手机端适配的问题(rem,页面缩放) 96 进击的小前端 关注 2018.02.02 13:57 字数 320 阅读 19评论 0喜欢 0 相信很多和会和我碰到一样的情况,就是你用rem去写移动端 ...

  5. python之路--装饰器

    二 .通用装饰器的写法 python里面的动态代理. 存在的意义: 在不破坏原有的函数和原有函数的调用基础上,给函数添加新的功能 def wrapper(fn): # fn是目标函数. def inn ...

  6. vue & iview

    vue & iview ui components https://codepen.io/webgeeker/pen/EJmQxQ https://www.iviewui.com/docs/g ...

  7. 莫烦keras学习自修第五天【CNN卷积神经网络】

    1.代码实战 #!/usr/bin/env python #! _*_ coding:UTF-8 _*_ import numpy as np np.random.seed(1337) # for r ...

  8. SQL Server 只安装客户端的方法

    只安装管理工具

  9. python时间模块datetime

    datetime模块 datetime在python中比较常用,主要用来处理时间日期,使用前先倒入datetime模块.下面总结下本人想到的几个常用功能. 1.当前时间(日期.小时.字符串时....) ...

  10. 错误代码 0x800700b7 配置错误定义了重复的“system.web.extensions/scripting/scriptResourceHandler”节

    如果是运行VS时就报错,改个端口号就可以解决问题,改完以下两个地方重新运行