简要题意

给你 \(N\) 本书 \((h_i,w_i)\),你要将书分成任意段(顺序不能改变),使得每一段 \(j\) 中 \(\sum\limits_{i \in j} w_i \leq L\),段 \(j\) 的代价为 \(\max\limits_{i \in j}{h_i}\)。你需要输出每一段的代价之和的最小值。

\(1 \leq N \leq 10^{5}\)

思路

朴素 DP 思路

设 \(f_i\) 为前 \(i\) 本书的代价和。则:

\[\begin{aligned}
& W(i,j) = \sum_{k=i}^{j}{w_k} \\
& H(i,j) = \max_{k=i}^{j}{h_k} \\
& f_i = \min_{W(j,i) \leq L}{(f_{j-1} + H(j,i))}
\end{aligned}
\]

解释:将 \([j,i]\) 中的书放在合并,然后成为一个新的段。

时间复杂度 \(O(n^3)\)。经过前缀和优化后 \(O(n^2)\),无法通过本题。

代码如下:

for(int i=1;i<=n;i++){
dp[i]=0x7f7f7f7f7fll;
sum[i]=sum[i-1]+w[i];
}
for(int i=1;i<=n;i++){
mn=INT_MIN;
for(int j=i;j>0;j--){
mn=max(mn,h[j]);
if(sum[i]-sum[j-1]<=m){
dp[i]=min(dp[i],dp[j-1]+mn);
}
else{
break;
}
}
}
cout<<dp[n];

喜提 \(69\operatorname{pts}\)

DP 优化

首先,最后一个满足 \(W(j,i) \leq l\) 的 \(j\) 是可以二分得出的(因为题目中 \(w\) 的前缀和是单调不降的)。我们姑且设其为 \(p_i\),则:

\[f_i = \min_{p_i}^{i}{(f_{j-1} + H(j,i))}
\]

另外我们设 \(l_i\) 为左边第一个满足 \(h_j>h_i\) 的 \(j\),即:

\[l_i = \max_{j=1}^{n}{(j \cdot [h_j > h_i])}
\]

那么如果 \(l_i \lt j \leq i\),则 \(H(j,i)=h_i\),只需要找到最小的 \(f_{j-1}\)即可。至于其他的,就用继承下来的。这是正确的。

这道题没法 ODT,老老实实的线段树。

代码

耗时最长的一道题祭

#include <bits/stdc++.h>
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
#define int long long
using namespace std; int f,n,l,h[100005],w[100005],sumw[100005]; namespace sgt{
struct node{
int f,fh,tag;
} t[400005];
void pushup(int i){
t[i].f=min(t[ls].f,t[rs].f);
t[i].fh=min(t[ls].fh,t[rs].fh);
}
void pushdown(int i){
if(t[i].tag!=(-1e9)){
t[ls].fh=t[ls].f+t[i].tag;
t[rs].fh=t[rs].f+t[i].tag;
t[ls].tag=t[i].tag;
t[rs].tag=t[i].tag;
t[i].tag=(-1e9);
}
}
void build(int i,int l,int r){
if(l==r){
t[i].fh=LLONG_MAX;
t[i].f=t[i].fh;
t[i].tag=(-1e9);
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
pushup(i);
}
void init(int p,int i,int l,int r){
if(l==r){
t[i].fh=LLONG_MAX;
t[i].f=f;
return;
}
pushdown(i);
if(p<=mid){
init(p,ls,l,mid);
}
else{
init(p,rs,mid+1,r);
}
pushup(i);
}
void assign(int ql,int qr,int k,int i,int l,int r){
if(ql<=l&&r<=qr){
t[i].fh=t[i].f+k;
t[i].tag=k;
return;
}
pushdown(i);
if(ql<=mid){
assign(ql,qr,k,ls,l,mid);
}
if(mid<qr){
assign(ql,qr,k,rs,mid+1,r);
}
pushup(i);
}
int get(int ql,int qr,int i,int l,int r){
if(ql<=l&&r<=qr){
return t[i].fh;
}
pushdown(i);
int ret=LLONG_MAX;
if(mid>=ql){
ret=min(ret,get(ql,qr,ls,l,mid));
}
if(mid<qr){
ret=min(ret,get(ql,qr,rs,mid+1,r));
}
return ret;
}
} stack<int> sta;
int lft[100005]; signed main(){
cin>>n>>l;
for(int i=1;i<=n;i++){
cin>>h[i]>>w[i];
sumw[i]=sumw[i-1]+w[i];
}
h[0]=INT_MAX;sta.push(0);
for(int i=1;i<=n;i++){
while(!sta.empty()&&h[i]>h[sta.top()]){
sta.pop();
}
lft[i]=sta.top();
sta.push(i);
}
sgt::build(1,1,n);
for(int i=1;i<=n;i++){
// cout<<"INIT "<<i<<'\n';
sgt::init(i,1,1,n);
// cout<<"ASSIGN "<<i<<'\n';
sgt::assign(lft[i]+1,i,h[i],1,1,n);
// cout<<"LOWERBOUND "<<i<<'\n';
int ll = lower_bound(sumw,sumw+i+1,sumw[i]-l)-sumw;
if(ll<i){
f=sgt::get(ll+1,i,1,1,n);
}
}
cout<<f;
}

P1848 [USACO12OPEN]Bookshelf G的更多相关文章

  1. 2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP)

    2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP) https://www.luogu.com.cn/problem/P1848 题意: 当农夫约翰闲 ...

  2. p1848 [USACO12OPEN]书架Bookshelf

    分析 单调队列优化dp即可 正确性显然,详见代码 代码 #include<bits/stdc++.h> using namespace std; #define int long long ...

  3. 解题:USACO12OPEN Bookshelf

    题面 从零开始的DP学习之肆 当DP方程中的一部分具有某种单调性时可以用数据结构或者预处理维护来降低复杂度 一开始没有看懂题,尴尬,后来发现题目可以简化成这个样子: 将一个序列划分为若干段,每段长度不 ...

  4. pkuwc 前的任务计划

    菜鸡 wxw 的计划(肯定会咕咕咕 12.27 luogu P4244 [SHOI2008]仙人掌图 II(咕咕咕 luogu P4246 [SHOI2008]堵塞的交通 (没有咕! luogu P1 ...

  5. Storyboards Tutorial 03

    这一节主要介绍segues,static table view cells 和 Add Player screen 以及 a game picker screen. Introducing Segue ...

  6. 文件图标SVG

    ​<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink ...

  7. [USACO12OPEN]书架Bookshelf

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

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

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

  9. [转]Linux下g++编译与使用静态库(.a)和动态库(.os) (+修正与解释)

    在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较熟悉,但是,在linux环境下,则是另一套模式,对应的静态库 ...

随机推荐

  1. 文本转语音TTS(文本阅读和视频配音制作)MP3

    DL-TTS 通过AI驱动引擎可将文本转化为逼真的语音,它可以:(1)生成逼真的合成语音实现与人声的语调和情感匹配的流畅.发音自然的文本转语音.(2)细化的文本转语音控制支持多种语言,并可调整语速.语 ...

  2. C++ 不知树系列之初识树(树的邻接矩阵、双亲孩子表示法……)

    1. 前言 树是一种很重要的数据结构,最初对数据结构的定义就是指对树和图的研究,后来才广义化了数据结构这个概念.从而可看出树和图在数结构这一研究领域的重要性. 树和图重要的原因是,它让计算机能建模出现 ...

  3. 《吐血整理》高级系列教程-吃透Fiddler抓包教程(31)-Fiddler如何抓取Android系统中Flutter应用程序的包

    1.简介 Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面.Flutter应用程序是用Dart编写的,这是一种由Google在7年多前创建的语言.Flut ...

  4. Blog1:nchu-software-oop-2022-1~3

    (1) 前言 针对在完成三次作业过程中产生的问题进行总结与分析. 三次作业一共十五(9+3+3)道题目,其中前两次难度较为简单,第三次复杂程度飞跃式上涨. 其中,涉及到java语言中基本的输入输出语句 ...

  5. 前后端分离项目(九):实现"添加"功能(后端接口)

    好家伙,来了来了,"查"已经完成了,现在是"增" 前端的视图已经做好了,现在我们来完善后端 后端目录结构   完整代码在前后端分离项目(五):数据分页查询(后端 ...

  6. Golang 加密方法

    如果想直接使用我下列的库 可以直接go get 我的github go get -u github.com/hybpjx/InverseAlgorithm md5 加密--不可逆 MD5信息摘要算法是 ...

  7. ES的java端API操作

    首先简单介绍下写这篇博文的背景,最近负责的一个聚合型的新项目要大量使用ES的检索功能,之前对es的了解还只是纯理论最多加个基于postman的索引创建操作,所以这次我得了解在java端如何编码实现:网 ...

  8. redis的缓存穿透、击穿、雪崩以及实用解决方案

    今天来聊聊redis的缓存穿透.击穿.雪崩以及解决方案,其中解决方案包括类似于布隆过滤器这种网上一搜一大片但是实际生产部署有一定复杂度的,也有基于spring注解通过一行代码就能解决的,其中各有优劣, ...

  9. 【题解】[ARC113C] String Invasion

    题面传送门 解决思路 题目大意是给你一个字符串 \(s\) ,定义一次操作为对于长度为 \(3\) 的一个子段,满足 \(s_i=s_{i+1}\ne s_{i+2}\),则可以将 \(s_{i+2} ...

  10. perl哈希嵌套和引用的使用

    数组,哈希嵌套 数组,哈希的引用 1.哈希的嵌套和引用 %hash = ( 'group1', {'fruit', 'banana', 'drink', 'orange juice', 'vegeta ...