解题:USACO12OPEN Bookshelf
从零开始的DP学习之肆
当DP方程中的一部分具有某种单调性时可以用数据结构或者预处理维护来降低复杂度
一开始没有看懂题,尴尬,后来发现题目可以简化成这个样子: 将一个序列划分为若干段,每段长度不超过$L$,求每段中最大值之和的最小值
看起来可以直接二分,然而大概并不可行,不过我们有一个明显的$O(n^2)$的DP思路,和我最近做的一道题思路一样。设$dp[i]$表示以$i$为结尾的最小花费,枚举结尾$i$,在$1->i$中找到所有与$i$间距不超过$L$的$j$来转移,代价就是$(j,i)$中的最大值,可以ST表预处理。即$dp[i]=min(dp[i],dp[j]+max(j,i))(j<=i\&\&\sum\limits_{k=j}^i width[k]<=L)$
考虑如何优化,发现$dp$数组在顺序下是单调不下降的,而当右端点$i$确定时,所有的$j$的最大值在顺序下是单调不上升的,所以我们可以考虑用线段树维护这个最小花费,也就是维护$dp[j]+max(j,i)$的最小值。我们枚举右端点时候相当于移动一个长度不超过$L$的滑动窗口,然后我们对于每个新加入的高度就维护一下它左边这段的最大高度,求出$dp[i]$后再单点修改一下下一个位置就可以了
具体来说是用线段树维护四个值+一个标记:最小值,最大值,dp数组,最小花费。其中最小值是为了在维护最大值的时候二分用的,当找到一个要修改的区间的时候我们二分出要修改的那一块,具体来说就是这块中的最小值小于我们要修改成的值再进去修改。然后说说这只蒟蒻都WA了什么鬼畜的错误,第一次是pushup用串了(雾);第二次是因为调试的时候写的和平时不太一样了,然后线段树release了叶子节点=。=;最后一次发现是区间没卡准(之前都是怎么过的2333)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
long long dp[*N],mini[*N],maxx[*N];
long long laz[*N],val[*N];
long long w[N],h[N];
long long n,m,f,tot,ans;
void pushup(int nde)
{
int ls=*nde,rs=*nde+;
maxx[nde]=max(maxx[ls],maxx[rs]);
mini[nde]=min(mini[ls],mini[rs]);
val[nde]=min(val[ls],val[rs]);
}
void release(int nde)
{
if(laz[nde])
{
int ls=*nde,rs=*nde+;
laz[ls]=mini[ls]=maxx[ls]=laz[nde];
laz[rs]=mini[rs]=maxx[rs]=laz[nde];
val[ls]=dp[ls]+maxx[ls],val[rs]=dp[rs]+maxx[rs]; laz[nde]=;
}
}
void change1(int nde,int l,int r,int nl,int nr,long long task)
{
if(l>nr||r<nl) return ;
if(l!=r) release(nde); int mid=(l+r)/,ls=*nde,rs=*nde+;
if(l>=nl&&r<=nr)
{
if(task<=maxx[nde])
{
if(task>mini[ls]) change1(ls,l,mid,nl,nr,task);
if(task>mini[rs]) change1(rs,mid+,r,nl,nr,task);
}
else
{
maxx[nde]=mini[nde]=laz[nde]=task;
val[nde]=dp[nde]+maxx[nde]; return ;
}
}
else
change1(ls,l,mid,nl,nr,task),change1(rs,mid+,r,nl,nr,task);
pushup(nde);
}
void change2(int nde,int l,int r,int pos,long long task)
{
if(l==pos&&r==pos) {dp[nde]=task; return ;}
release(nde); int mid=(l+r)/,ls=*nde,rs=*nde+;
if(pos<=mid) change2(ls,l,mid,pos,task);
else change2(rs,mid+,r,pos,task);
dp[nde]=min(dp[ls],dp[rs]);
}
long long query(int nde,int l,int r,int nl,int nr)
{
if(l>nr||r<nl)
return 1e18;
else if(l>=nl&&r<=nr)
return val[nde];
else
{
int mid=(l+r)/,ls=*nde,rs=*nde+; release(nde);
return min(query(ls,l,mid,nl,nr),query(rs,mid+,r,nl,nr));
}
}
int main ()
{
scanf("%lld%lld",&n,&m),f=;
for(int i=;i<=n;i++)
scanf("%lld%lld",&h[i],&w[i]);
for(int i=;i<=n;i++)
{
tot+=w[i];
while(tot>m) tot-=w[f++];
change1(,,n,,i,h[i]);
ans=query(,,n,f,i);
if(i!=n) change2(,,n,i+,ans);
}
printf("%lld",ans);
return ;
}
解题:USACO12OPEN Bookshelf的更多相关文章
- 2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP)
2021.12.08 P1848 [USACO12OPEN]Bookshelf G(线段树优化DP) https://www.luogu.com.cn/problem/P1848 题意: 当农夫约翰闲 ...
- [USACO12OPEN]书架Bookshelf
Description 当农夫约翰闲的没事干的时候,他喜欢坐下来看书.多年过去,他已经收集了 N 本书 (1 <= N <= 100,000), 他想造一个新的书架来装所有书. 每本书 i ...
- [Luogu1848][USACO12OPEN]书架Bookshelf DP+set+决策单调性
题目链接:https://www.luogu.org/problem/show?pid=1848 题目要求书必须按顺序放,其实就是要求是连续的一段.于是就有DP方程$$f[i]=min\{f[j]+m ...
- p1848 [USACO12OPEN]书架Bookshelf
分析 单调队列优化dp即可 正确性显然,详见代码 代码 #include<bits/stdc++.h> using namespace std; #define int long long ...
- POJ 3268 Bookshelf 2 动态规划法题解
Description Farmer John recently bought another bookshelf for the cow library, but the shelf is gett ...
- SCNU ACM 2016新生赛决赛 解题报告
新生初赛题目.解题思路.参考代码一览 A. 拒绝虐狗 Problem Description CZJ 去排队打饭的时候看到前面有几对情侣秀恩爱,作为单身狗的 CZJ 表示很难受. 现在给出一个字符串代 ...
- SCNU ACM 2016新生赛初赛 解题报告
新生初赛题目.解题思路.参考代码一览 1001. 无聊的日常 Problem Description 两位小朋友小A和小B无聊时玩了个游戏,在限定时间内说出一排数字,那边说出的数大就赢,你的工作是帮他 ...
- HDU 3791二叉搜索树解题(解题报告)
1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...
- 【BZOJ1700】[Usaco2007 Jan]Problem Solving 解题 动态规划
[BZOJ1700][Usaco2007 Jan]Problem Solving 解题 Description 过去的日子里,农夫John的牛没有任何题目. 可是现在他们有题目,有很多的题目. 精确地 ...
随机推荐
- 【CentOS 7】nginx配置web服务器
1,安装过程 [root@VM_1_14_centos ~]# cd /data/ [root@VM_1_14_centos data]# wget http://nginx.org/download ...
- tf导出pb文件,以及如何使用pb文件
先罗列出来代码,有时间再解释 from tensorflow.python.framework import graph_util import tensorflow as tf def export ...
- ossec安装
安装 安装要求 对于Unix系统来说,OSSEC只需要GNU的make.gcc和libc.推荐使用OpenSSL,但仅属于一个可选项.而且,通常您只需在一个系统上做编译操作,然后将二进制程序复制到其他 ...
- [机器学习]-K近邻-最简单的入门实战例子
本篇文章分为两个部分,前一部分主要简单介绍K近邻,后一部分是一个例子 第一部分--K近邻简介 从字面意思就可以容易看出,所谓的K近邻,就是找到某个样本距离(这里的距离可以是欧式距离,曼哈顿距离,切比雪 ...
- 1.Python3.6环境部署
标题:Python3.6环境部署文档 作者:刘耀 内容 Linux部署Python3.6环境 Mac部署Python3.6环境 Window10部署Python3.6环境 Pycharm安装 1. L ...
- 字符串匹配:KMP算法, Boyer-Moore算法理解与总结
1. KMP算法是前缀匹配算法,一次从前往后匹配的过程中,根据已经部分匹配的信息,在文本中,移动尽可能远的距离.而不是按照朴素模式匹配方法,每次都只移动一个位置. 比如这个示例,在文本串中从4(从0开 ...
- PHP 抽象类和接口区别
php中抽象类和接口的区别 1) 概念 面向对象的三大概念:封装,继承,多态 把属性和方法封装起来就是类. 一个类的属性和方法被另外的类复制就是继承,PHP里面的任何类都可以被继承,被继承的 ...
- 浏览器差异bug汇总(js篇)
获取滚动条高度 var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; safari浏览器时间函数 ...
- oracle和mysql在sql中生成uuid的方法
1,oracle sys_guid() 2,mysql uuid()
- spring冲刺第三天
昨天完成了环境配置和初步的地图设想. 今天从网上找了有关这方面的例子,运行试验了一番.编写的地图画面在程序上运行了一下,有些错误,还需要很多方面的改进. 这些例子有很多地方都不太懂,但还是看完了.我认 ...