洛谷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方案数]
题目描述 “低价购买”这条建议是在奶牛股票市场取得成功的一半规则.要想被认为是伟大的投资者,你必须遵循以下的问题建议:“低价购买:再低价购买”.每次你购买一支股票,你必须用低于你上次购买它的价格购买它 ...
随机推荐
- JavaScript lastIndexOf() 方法
<script type="text/javascript"> var str="0000.0000.0000.0000.0000.0000.0000.&qu ...
- C++多态(静多态和动多态)
如今的C++已经是个多重泛型编程语言(multiparadigm programming lauguage),一个同时支持过程形式(procedural).面向对象形式(object-oriented ...
- 剑指offer(1)
题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...
- div中的相对定位与绝对定位
1.position:relative; 如果对一个元素进行相对定位,首先它将出现在它所在的位置上.然后通过设置垂直或水平位置,让这个元素“相对于”它的原始起点进行移动.(再一点,相对定位时,无论是否 ...
- java 中的迭代
package cn.zhou.com; import java.util.ArrayList; import java.util.Collection; import java.util.Itera ...
- Python——管道通信
管道:双向通信 2个进程之间相互通信 from multiprocessing import Pipe,Process def func(conn1,conn2): conn2.close() whi ...
- java 运行 .jar 文件乱码
http://yang3wei.github.io/blog/2013/02/10/java-dfile-dot-encoding-equals-utf-8-gan-diao-luan-ma/ 启动时 ...
- if 结构语句
if 条件: print()#不只是能输入print
- node.js 运行机制与简单使用
一.hello world 1.引入 required 模块 2.创建服务器 3.接收请求与响应请求 var http = require('http'); // 载入http模块 http.crea ...
- codeforces1101D GCD Counting 【树形DP】
题目分析: 蛮简单的一道题,对于每个数拆质因子,对于每个质因子找出最长链,在每个地方枚举一下拼接 代码: #include<bits/stdc++.h> using namespace s ...