TJOI2011书架(dp)
当农夫约翰闲的没事干的时候,他喜欢坐下来看书。多年过去,他已经收集了 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)的更多相关文章
- P1295 [TJOI2011]书架 线段树优化dp,单调栈
P1295 [TJOI2011]书架 本题思路比较好想(对我来说不是),但代码细节很多,奈何洛谷的题解只有思路,然后就是 没有丝毫解释的代码,让人看起来很头疼(~~ 尤其是像我这样的蒟蒻~~),所以便 ...
- BZOJ5125: [Lydsy1712月赛]小Q的书架【决策单调性优化DP】【BIT】【莫队】【分治】
小Q有n本书,每本书有一个独一无二的编号,现在它们正零乱地在地上排成了一排. 小Q希望把这一排书分成恰好k段,使得每段至少有一本书,然后把每段按照现在的顺序依次放到k层书架的每一层上去.将所有书都放到 ...
- Codeforces 981 共同点路径覆盖树构造 BFS/DP书架&最大值
A /*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_bac ...
- [BZOJ5125]小Q的书架(决策单调性+分治DP+树状数组)
显然有决策单调性,但由于逆序对不容易计算,考虑分治DP. solve(k,x,y,l,r)表示当前需要选k段,待更新的位置为[l,r],这些位置的可能决策点区间为[x,y].暴力计算出(l+r)/2的 ...
- BZOJ5125: [Lydsy1712月赛]小Q的书架(DP决策单调性)
题意:N个数,按顺序划分为K组,使得逆序对之和最小. 思路:之前能用四边形不等式写的,一般网上都还有DP单调性分治的做法,今天也尝试用后者写(抄)了一遍.即: 分成K组,我们进行K-1次分治,get( ...
- [Luogu1848][USACO12OPEN]书架Bookshelf DP+set+决策单调性
题目链接:https://www.luogu.org/problem/show?pid=1848 题目要求书必须按顺序放,其实就是要求是连续的一段.于是就有DP方程$$f[i]=min\{f[j]+m ...
- LightOJ1283 Shelving Books(DP)
题目 Source http://www.lightoj.com/volume_showproblem.php?problem=1283 Description You are a librarian ...
- [USACO12OPEN]书架Bookshelf
Description 当农夫约翰闲的没事干的时候,他喜欢坐下来看书.多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书. 每本书 i ...
- DP擎天
DP! 黄题: 洛谷P2101 命运石之门的选择 假装是DP(分治 + ST表) CF 982C Cut 'em all! 树形贪心 洛谷P1020 导弹拦截 单调队列水题 绿题: 洛谷P1594 护 ...
随机推荐
- 百度地图api在Html中显示,在jsp页面中不显示解决方法
在jsp页面中显示如下 但是在html中正常显示. 原来的代码如下: <script type="text/javascript" src="http://api. ...
- 树遍历(广度优先 vs 深度优先)
const data = [ { id: '01', text: '湖北省', children: [ { id: '01001', text: '武汉市', children: [ { id: '0 ...
- java对象的四种引用:强引用、软引用、弱引用和虚引用
在JDK1.2之前,创建的对象只有在处于可触及(reachable)的状态下,才能被程序使用.也就是说,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.垃圾回收器一旦发现这些无用对象,就会对 ...
- css太极
自己用css做的太极,留个纪念. 用css做太极有很多种实现方法,我这种大概是最简单的了吧,因为div用得太多了,哈哈. 高级一点的应该是用伪类:before和:after去减少div的用量(手动滑稽 ...
- Python 命令行工具 argparse 模块使用详解
先来介绍一把最基本的用法 import argparse parser = argparse.ArgumentParser() parser.parse_args() 在执行 parse_args() ...
- 常见IT工具软件总结
1. 阿里云在线迁移服务 2.智能媒体管理 格式转换 业务域名管理 1. 每个业务有一个英文单词, 1. 每个 git 的命名应该是 chgg-业务英文-种类 2. 例如 chgg-plant-api ...
- Python自动化运维ansible从入门到精通
1. 下载安装 在windows下安装ansible:
- Scss - 简单笔记
原文链接:scss 教程 手头上疯狂在用 scss,虽然可以在里面写原生的 css, 但是为了保持风格的一致性,还是滚去看了看 scss 文档. 一.变量 变量的引入是 scss 的一个核心特性,变量 ...
- 【Python】一份非常好的Matplotlib教程
Matplotlib 教程 本文为译文,原文载于此,译文原载于此.本文欢迎转载,但请保留本段文字,尊重作者和译者的权益.谢谢.: ) 介绍 Matplotlib 可能是 Python 2D-绘图领域使 ...
- python基础数据类型--list列表
列表: 列表是python中的基础数据类型之一,其他语言中也有类似于列表的数据类型,比如js中叫数组,他是以[]括起来,每个元素以逗号隔开,而且他里面可以存放各种数据类型比如: li = [‘alex ...