洛谷 P3580 - [POI2014]ZAL-Freight(单调队列优化 dp)
考虑一个平凡的 DP:我们设 \(dp_i\) 表示前 \(i\) 辆车一来一回所需的最小时间。
注意到我们每次肯定会让某一段连续的火车一趟过去又一趟回来,故转移可以枚举上一段结束位置,设为 \(j\),那么有转移
\]
在这里我们不妨假设 \(a_i<a_{i+1}\),这个可以通过从左到右扫一遍并执行 \(a_i\leftarrow\max(a_{i-1}+1,a_i)\) 实现。
稍微解释一下上面的式子,由于一趟来回,那么我们肯定会让前面的车都等到第 \(i\) 辆车到达对面后再返回,而第 \(i\) 辆车发车的时间是 \(\max(dp_j+j-i-1,a_i)\),因此第 \(i\) 辆车到达对面的最早时间就是 \(\max(dp_j+j-i-1,a_i)+s\)。而全部 \(j-i+1\) 辆车返程的时间又是 \(s+j-i+1\),总时间就是 \(\max(dp_j+j-i-1,a_i)+2s+j-i-1\)。
如何优化?考虑单调队列。我们考虑拆 \(\max\)。如果 \(dp_j+i-j-1\ge a_i\),也就是 \(dp_j-j\ge a_i-i+1\),\(\max\) 会取到 \(dp_j+i-j-1\),此时 \(dp_j+2s+2i-2j-2\leftarrow dp_i\),我们维护 \(dp_j-2j\) 的最大值即可实现,具体来说,根据 \(dp\) 数组的实际含义,有 \(dp_j-j\) 是单调不降的,因此我们考虑维护一个 \(dp_j-j\) 递增,\(dp_j-2j\) 递减的单调队列,每次 pop 掉队首直到队首元素符合 \(dp_j-j\ge a_i-i+1\) 然后用它更新答案即可。
如果 \(dp_j+i-j-1<a_i\),那么 \(a_i+2s+i-j-1\leftarrow dp_i\),因此我们只用维护 pop 出去的元素的 \(-j\) 的最小值即可,而由于我们是按照 \(j\) 递增的顺序将 \(j\) 的贡献加入单调队列的,因此 \(-j\) 的最小值肯定在上一个被 pop 出去的元素处取到,直接更新答案即可。
时间复杂度线性。
感觉和 AGC 007D 有点像(
应该是 CSP 之前除了模拟赛之外刷的最后一道题了(
using namespace fastio;
const int MAXN=1e6;
int n,s,a[MAXN+5],q[MAXN+5],hd=1,tl=1;ll dp[MAXN+5];
ll calc(int x,int y){return max(1ll*a[y],dp[x]+y-x-1)+2*s+y-x-1;}
int main(){
read(n);read(s);a[0]=-1;
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++) a[i]=max(a[i-1]+1,a[i]);
memset(dp,63,sizeof(dp));dp[0]=0;
for(int i=1;i<=n;i++){
while(hd<tl&&dp[q[hd]]-q[hd]<a[i]-i+1) ++hd;
if(hd<=tl) chkmin(dp[i],calc(q[hd],i));
if(hd>1) chkmin(dp[i],calc(q[hd-1],i));
while(hd<tl&&dp[q[tl]]-2*q[tl]>=dp[i]-2*i) --tl;
q[++tl]=i;
}
printf("%lld\n",dp[n]);
return 0;
}
洛谷 P3580 - [POI2014]ZAL-Freight(单调队列优化 dp)的更多相关文章
- 2018.09.26洛谷P3957 跳房子(二分+单调队列优化dp)
传送门 表示去年考普及组的时候失了智,现在看来并不是很难啊. 直接二分答案然后单调队列优化dp检验就行了. 注意入队和出队的条件. 代码: #include<bits/stdc++.h> ...
- 洛谷 P3957 跳房子 —— 二分答案+单调队列优化DP
题目:https://www.luogu.org/problemnew/show/P3957 先二分一个 g,然后判断: 由于转移的范围是一个区间,也就是滑动窗口,所以单调队列优化: 可以先令队尾为 ...
- 洛谷P1725琪露诺(单调队列优化dp)
P1725 琪露诺 题目描述 在幻想乡,琪露诺是以笨蛋闻名的冰之妖精.某一天,琪露诺又在玩速冻青蛙,就是用冰把青蛙瞬间冻起来.但是这只青蛙比以往的要聪明许多,在琪露诺来之前就已经跑到了河的对岸.于是琪 ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【bzoj3831】[Poi2014]Little Bird 单调队列优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6826475.html 题目描述 In the Byteotian Line Forest there are t ...
- 洛谷p1725 露琪诺 单调队列优化的DP
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...
- bzoj3831 [Poi2014]Little Bird 单调队列优化dp
3831: [Poi2014]Little Bird Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 505 Solved: 322[Submit][ ...
- 【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)
Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮 ...
- 洛谷P3195 [HNOI2008]玩具装箱TOY(单调队列优化DP)
题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...
随机推荐
- HashMap、ConcurrentHashMap红黑树实现分析
本文学习知识点 1.二叉查找树,以及二叉树查找带来的问题. 2.平衡二叉树及好处. 3.红黑树的定义及构造. 4.ConcurrentHashMap中红黑树的构造. 在正式分析红黑树之前,有必要了解红 ...
- 395.至少有 K 个重复字符的最长子串
题目 给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于k .返回这一子串的长度. 示例 1: 输入:s = "aaabb" ...
- 欧姆龙PLC HostLink协议整理
欧姆龙PLC HostLink协议整理 1.常用的存储器功能区 CIO: 输入继电器 272 点(17 CH) 0.00-16.15 输出继电器 272 点(17 CH) 100.00-116.1 ...
- “妈妈再也不用担心我忘交作业了!”——记2020BUAA软工团队项目选择
写在前面 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 团队项目选择 项目简介 项目名称:北航学生资源整合和作业提醒平台 项目内容: 设计实现一 ...
- BUAA 2020 软件工程 个人项目作业
BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...
- NKOJ-4573 Falsita
问题描述: 到海边了呢...... 如果没有那次选择,现在是不是会好些呢...... 都过去了. 仰望着星空,迎面吹过一阵阵海风,倚靠着护栏,Fine 在海边静静地伫立着,在一个个无际的长夜后,Fin ...
- c语言编程基础入门必备知识
数据类型 基本数据类型 类型名称说明char字符类型存放字符的ASCII码int整型存放有符号整数short短整型存放有符号整数long长整型存放有符号整数long long存放有符号整数float单 ...
- .NET 5 全自动分表组件,.NET 分表方案 ,分表架构与设计
一.疑问&目的 1.1 分表使用场景 (1)可扩展架构设计,比如一个ERP用5年不卡,到了10就卡了因为数据太多了,这个时候很多人都是备份然后清空数据,这个工作大并且麻烦,以前的数据很难在使用 ...
- Spring Boot 2.5.0 重新设计的spring.sql.init 配置有何用?
前几天Spring Boot 2.5.0发布了,其中提到了关于Datasource初始化机制的调整,有读者私信想了解这方面做了什么调整.那么今天就要详细说说这个重新设计的配置内容,并结合实际情况说说我 ...
- hdu 5102 The K-th Distance (队列+生成法,,)
题意: N个点的一棵树.定义点u和点v的距离等于它们之间的路径(唯一的)的长度.这样我们可以得到n*(n-1)/2个距离. 将它们从小到大排序,问前K个数的和是多少. 思路: 将边长为1的树枝都入队列 ...