洛谷P1848 书架
好,我一直以为书架是splay,然后发现还有个优化DP的书架。妃的书架
蓝书和PPT上面都讲了,应该比较经典吧。
题意:
有n个物品,每个都有宽,高。
把它们分成若干段,使得每段的最大值的总和最小。且每段的总宽度不超过L。
n <= 100000
解:
首先有个很显然的DP是f[i] = min(f[j] + max(j + 1, i)), sum[i] - sum[j] <= L
然后如何优化呢?因为有max函数(非线性)所以难以单调队列。把决策打出来发现不单调。无计可施???
发现当i固定的时候,max(j + 1, i)是一段一段单减的。这样相当于能确定状态转移方程中的后者。
再看前者,f[j]这个东西,其实是单调不减的。证明:把f[j - 1]按照f[j]的方式划分即可<=f[j]。
怎么利用呢?朴素的想法是把每一个数前面最大的数用单调栈求出来,记为to[]数组。
那么每次转移的时候跳to[]即可。可以发现在区间(to[i], i)之间的转移都不优于to[i]。
这里忽视了一个小问题,有个宽度限制在这里。我的解决办法是用pos记录最早的一个能够转移过来的位置。pos的维护显然是线性的。
这个好想好写的东西最坏复杂度还是n²,递增序列就能卡掉,然而交上去有90分......
来考虑正解。我们能不能每次不跳to[]链,而是更快的求出最小值来转移呢?
很容易(困难)想到用堆维护。对于失效的转移用延迟删除法。
问题就只剩如何判断转移失效了。
如果转移的j < pos,显然不行。此外,如果j不在以i开头的to链上,也是不行的。
有个朴素的想法是用数组维护是否在to链上,即每次把i前面比i小的舍去,但是又会被递增卡成n²。
仔细思考,发现以i开头的to链就是单调栈在处理到i时的栈内元素。
于是我们一边DP一边维护单调栈,只需判断j是在否在栈中即可。
至此,时间复杂度优化为nlogn,可以通过此题。
记得开long long
#include <cstdio>
#include <algorithm>
#include <queue>
#define mp std::make_pair typedef long long LL;
const int N = ; LL f[N], sum[N];
int st[N][], pow[N], n, to[N], p[N], top;
bool in_stk[N];
std::priority_queue<std::pair<LL, int> > Q; inline void STinit() {
int j = , lm = ;
while(( << lm) <= n) {
while(j < ( << (lm + )) && j <= n) {
pow[j] = lm;
j++;
}
lm++;
}
for(int j = ; j < lm; j++) {
for(int i = ; i + ( << j) - <= n; i++) {
st[i][j] = std::max(st[i][j - ], st[i + ( << (j - ))][j - ]);
}
}
return;
} inline int getmax(int l, int r) {
int t = pow[r - l + ];
return std::max(st[l][t], st[r - ( << t) + ][t]);
} int main() {
int L;
scanf("%d%d", &n, &L);
for(int i = ; i <= n; i++) {
scanf("%d%lld", &st[i][], &sum[i]);
sum[i] += sum[i - ];
f[i] = 1ll << ;
} STinit();
st[][] = 0x7f7f7f7f;
to[] = -; int pos = ;
for(int i = ; i <= n; i++) {
while(st[i][] >= st[p[top]][]) {
in_stk[p[top]] = ;
top--;
}
to[i] = p[top];
p[++top] = i;
in_stk[i] = ; Q.push(mp(- * (f[to[i]] + getmax(to[i] + , i)), i)); while(sum[i] - sum[pos] > L) {
pos++;
}
while((!Q.empty()) && (to[Q.top().second] < pos || (!in_stk[Q.top().second]))) {
Q.pop();
}
if(!Q.empty()) {
f[i] = - * Q.top().first;
}
f[i] = std::min(f[i], f[pos] + getmax(pos + , i));
}
/*for(int i = 1; i <= n; i++) {
printf("%lld ", f[i]);
}*/
printf("%lld", f[n]);
return ;
}
AC代码
但是还有很多可以改进的地方。
比如to这个数组可否舍去?ST表可否舍去?我是懒得优化了T_T
洛谷P1848 书架的更多相关文章
- 洛谷P3850 书架
题目描述 Knuth先生家里有个精致的书架,书架上有N本书,如今他想学到更多的知识,于是又买来了M本不同的新书.现在他要把新买的书依次插入到书架中,他已经把每本书要插入的位置标记好了,并且相应的将它们 ...
- 洛谷P2468 SDOI 2010 粟粟的书架
题意:给你一个矩形书架,每个点是这本书的页数,每次询问(x1,y1)(x2,y2)这个小矩形里最少需要取几本书使得页数和等于Hi. 题解:小数据二位前缀和预处理+二分答案,大数据一行所以用主席树做,感 ...
- [洛谷P2596] [ZJOI2006]书架
洛谷题目链接:书架 题目描述 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后 ...
- 洛谷P2468 [SDOI2010]粟粟的书架
来了来了,随便拽一道题写题解[大雾] 最近发现自己基础奇差于是开始复习之前学过的东西,正好主席树我几乎完全没学会,然后打开洛谷试炼场… 发现了这么一道二合一的题. 这道题其实分成两个部分,前50%是一 ...
- 洛谷P2464 [SDOJ2008]郁闷的小J
洛谷P2464 [SDOJ2008]郁闷的小J 题目描述 小J是国家图书馆的一位图书管理员,他的工作是管理一个巨大的书架.虽然他很能吃苦耐劳,但是由于这个书架十分巨大,所以他的工作效率总是很低,以致他 ...
- 洛谷 P1103 书本整理(动规)
洛谷 P1103 书本整理 题目描述 Frank是一个非常喜爱整洁的人.他有一大堆书和一个书架,想要把书放在书架上.书架可以放下所有的书,所以Frank首先将书按高度顺序排列在书架上.但是Frank发 ...
- 洛谷1640 bzoj1854游戏 匈牙利就是又短又快
bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...
- 洛谷P1352 codevs1380 没有上司的舞会——S.B.S.
没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description Ural大学有N个职员,编号为1~N.他们有 ...
- 洛谷P1108 低价购买[DP | LIS方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
随机推荐
- 【学亮IT手记】Servlet的生命周期
1.1 Servlet的生命周期 1.1.1 Servlet的生命周期概述 1.1.1.1 什么是生命周期 生命周期:一个对象从创建到销毁过程. 1.1.1.2 Servlet的生命周期(*****) ...
- 为linux主机增加file description
在benchmarked写的服务器的时候就遇到了too many file open 这个报错. 由于遇到过很多次了,所以知道应该是单机fd打满了. 首先来看看 机器最多支持多少fd cat /pro ...
- MySQL磁盘写入策略以及数据安全性的相关参数
转载自:http://blog.itpub.net/22664653/viewspace-1063134/ innodb_flush_log_at_trx_commit和sync_binlog ...
- php配置-解决大数据超多字段的POST方式提交无法完全接受的问题
例如:在盘点表的数据提交中出现了POST大量数据超多字段的将近2000个字段,部分字段没有接受:修改方法为修改php.ini 将max_input_var调大,该值默认为1000 max_input_ ...
- jquery的show()和hide()方法
显示和隐藏元素的方法 相当于CSS中的display属性 show()方法,相当于display:block hide()方法,相当于display:none
- C#使用MemoryStream类读写内存
MemoryStream和BufferedStream都派生自基类Stream,因此它们有很多共同的属性和方法,但是每一个类都有自己独特的用法.这两个类都是实现对内存进行数据读写的功能,而不是对持久性 ...
- SQL Server中获取指定时间段内的所有月份
例如查询 2012-1-5 到 2012-11-3 之间所有的月份 declare @begin datetime,@end datetime set @begin='2012-1-5' set @e ...
- Mac下搭建PHP服务器
打开终端 1. 输入 sudo vi /etc/apache2/httpd.conf 2.把167-170的前面#去掉即加载下面几个模块 1.LoadModule alias_module libe ...
- Django通用视图APIView和视图集ViewSet的介绍和使用
原 Django通用视图APIView和视图集ViewSet的介绍和使用 2018年10月21日 14:42:14 不睡觉假扮古尔丹 阅读数:630 1.APIView DRF框架的视图的基类是 ...
- 基于junit的单元测试类编写
首先定义抽象类BaseTest package com.geostar.gfstack.operationcenter.common.util; import com.google.gson.Gson ...