AtCoder agc007_d Shik and Game
洛谷题目页面传送门 & AtCoder题目页面传送门
有\(1\)根数轴,Shik初始在位置\(0\)。数轴上有\(n\)只小熊,第\(i\)只在位置\(a_i\)。Shik每秒可以向左移动\(1\)个单位长度、原地不动或向右移动\(1\)个单位长度。Shik第\(1\)次到某个小熊的位置\(s\)秒后,小熊会在原地生产\(1\)个金币,Shik必须再次到达此小熊的位置才能收集金币。求Shik收集完所有金币后到达位置\(m\)所花的最小秒数。
\(n\in\left[1,10^5\right],a_i\in(0,m),a_i<a_{i+1}\)。
考虑最优情况下,Shik的路线会是怎样的。如果Shik经过了一些小熊,回头收集了这些小熊中后面一部分的金币,然后继续往终点走,留下前面一部分金币等到以后再收,这样肯定不是最优的(感性理解)。可以推出若一个小熊的金币被收了,那么它前面的所有小熊的金币都被收了,即被收了金币的小熊序列是所有小熊序列的一个前缀。考虑将某时刻的前缀分成若干个区间,每个区间内的小熊都是在一次回头中被收了金币的,于是我们就可以DP了。
设\(dp_i\)表示Shik收完了前\(i\)个小熊的金币并回到了位置\(a_i\)所花的最小秒数。不妨设\(a_0=0\)为起点。那么显然边界是\(dp_0=0\),目标是\(dp_n+m-a_n\)。转移的话,枚举当前被收了金币的小熊前缀被划分的最后一个区间的左端点的前一个小熊\(j\),即最后一次回头之前\([1,j]\)已经被收了。那么最后一次回头收的是\([j+1,i]\)。显然,路线是这样的:先将前\(j\)个小熊的金币收完,回到位置\(a_j\),然后\(a_j\to a_i\)经过\([j+1,i]\)使它们生产金币,然后\(a_i\to a_{j+1}\)回头到第\(j+1\)个小熊,等待若干秒直到第\(j+1\)个小熊生产金币,然后\(a_{j+1}\to a_i\)依次收完\([j+1,i]\)的金币并回到位置\(a_i\)。那么状态转移方程就很好列了:
\]
即
\]
暴力转移显然是\(\mathrm O\!\left(n^2\right)\)的,于是考虑优化。注意到方程里有个\(\max\)很不好处理,于是分类讨论,分成\(s-2a_i+2a_{j+1}\ge0\)和\(s-2a_i+2a_{j+1}<0\)这\(2\)种。此时方程变为了:(化简后)
\]
将关于决策变量\(j\)的放到一起,关于状态变量\(i\)的和常量放到一起,得
\]
\(2\)个\(\min\)的条件里的\(2a_{j+1}\)显然有单调性,所以\(2\)个\(\min\)取的\(j\)都构成区间。特殊地,对于第\(2\)个\(\min\),是前缀,即左端点为\(0\)的区间。又因为\(2a_i-s\)也有单调性,所以第\(1\)个\(\min\)的区间左端点单调递增,对于每个\(i\),这个左端点可以two-pointers求出。于是对于第\(1\)个\(\min\)维护单调队列,对于第\(2\)个\(\min\)维护前缀最小值,\(\mathrm O(n)\)。
下面贴代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long//防爆int
const int inf=0x3f3f3f3f3f3f3f3f;
const int N=100000;
int n/*小熊个数*/,m/*终点*/,s/*小熊被Shik碰到至生产金币之间的秒数*/;
int a[N+1];//小熊的位置
int dp[N+1];//dp[i]表示Shik收完了前i个小熊的金币并回到了位置a[i]所花的最小秒数
int q[N],head,tail;//对于第1个min维护的单调队列
signed main(){
cin>>n>>m>>s;
for(int i=1;i<=n;i++)cin>>a[i];
q[tail++]=0;//i=1,j=0满足2a[j+1]>=2a[i]-t,归第1个min,于是压入单调队列
int now=-1/*第2个min取的j构成的区间(前缀)的右端点*/,mn=inf/*当前的前缀最小值*/;
for(int i=1;i<=n;i++){
while(now+1<i&&2*a[now+2]<2*a[i]-s)now++,mn=min(mn,dp[now]-a[now]-2*a[now+1]);//将now往后移
while(head<tail&&q[head]<=now)head++;//维护单调队列,弹出过时元素
while(head<tail&&dp[q[tail-1]]-a[q[tail-1]]>=dp[i-1]-a[i-1])tail--;//维护单调队列队尾严格单调递增性
q[tail++]=i-1;//将j=i-1入队
dp[i]=min(dp[q[head]]-a[q[head]]+a[i]+s,mn+3*a[i]);//状态转移方程
}
cout<<dp[n]+m-a[n]<<"\n";//目标
return 0;
}
AtCoder agc007_d Shik and Game的更多相关文章
- AtCoder AGC007E Shik and Travel (二分、DP、启发式合并)
题目链接 https://atcoder.jp/contests/agc007/tasks/agc007_e 题解 首先有个很朴素的想法是,二分答案\(mid\)后使用可行性DP, 设\(dp[u][ ...
- 【AtCoder Grand Contest 007E】Shik and Travel [Dfs][二分答案]
Shik and Travel Time Limit: 50 Sec Memory Limit: 512 MB Description 给定一棵n个点的树,保证一个点出度为2/0. 遍历一遍,要求每 ...
- AtCoder Grand Contest 007 E:Shik and Travel
题目传送门:https://agc007.contest.atcoder.jp/tasks/agc007_e 题目翻译 现在有一个二叉树,除了叶子每个结点都有两个儿子.这个二叉树一共有\(m\)个叶子 ...
- AtCoder Grand Contest 007
AtCoder Grand Contest 007 A - Shik and Stone 翻译 见洛谷 题解 傻逼玩意 #include<cstdio> int n,m,tot;char ...
- AtCoder刷题记录
构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
- AtCoder Grand Contest 001 C Shorten Diameter 树的直径知识
链接:http://agc001.contest.atcoder.jp/tasks/agc001_c 题解(官方): We use the following well-known fact abou ...
- AtCoder Regular Contest 082
我都出了F了……结果并没有出E……atcoder让我差4分上橙是啥意思啊…… C - Together 题意:把每个数加1或减1或不变求最大众数. #include<cstdio> #in ...
- AtCoder Regular Contest 069 D
D - Menagerie Time limit : 2sec / Memory limit : 256MB Score : 500 points Problem Statement Snuke, w ...
随机推荐
- C语言传递二维数组
方法一, 形参给出第二维的长度. 例如: #include <stdio.h> ] ) { int i; ; i < n; i++) printf("/nstr[%d] = ...
- openresty-component
1.Array Var Nginx Module ArrayVarNginxModulelocation /foo { array_split ',' $arg_files to=$array; # ...
- php虚拟主机下实现定时任务(仅供参考)
因为要做简单的中控 在实现心跳包的时候遇到了困难 正常的心跳包思路是这样的 举个例子 我写一个登陆签到脚本 当我登陆成功的时候 会把登陆成功这个状态传递给网络上的中控端 当我签到完成的时候会把 ...
- Spring_002 依赖注入方式实现
继续写我们的第一个Spring程序,这次我们使用依赖注入的方式实现程序 第一步,建立我们的Spring_002程序,并在程序中添加BookDao.java.BookDaoImpl.java.BookS ...
- tab 切换 和 BottomNavigationBar 自定义 底部导航条
BottomNavigationBar 组件 BottomNavigationBar 是底部导航条,可以让我们定义底部 Tab 切换,bottomNavigationBar是 Scaffold ...
- C++中map的介绍用法以及Gym题目:Two Sequences
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字(key),每个关键字只能在map中出现一次,第二个可能称为该关键字的值(value))的数据 处理能力,由于这个特性,它完成有可能 ...
- 【Struts 编码】
EncodingFilter package k.filter; import javax.servlet.*; import javax.servlet.http.HttpServlet; impo ...
- VS2017创建控制台应用后,编写完代码调试正常,使用exe文件直接执行出现闪退情况解决方法。
这是因为代码中包含的相对路径的原因. 解决办法:把项目中包含的所有相对路径修改为绝对路径. (个人觉得因为直接执行exe文件,默认打开在C盘的用户目录下.) 例如: std::string DATA_ ...
- 4_5 追踪电子表格中的单元格(UVa512)(选做)
在电子表格中的数据都存储在单元格中,它是按行和列(R)(C).一些在电子表格上的操作可以应用于单个单元格(研发),而其他的可以应用于整个行或列.典型的单元操作包括插入和删除行或列和交换单元格内容.一些 ...
- PB 数据窗口点击标题不能排序的一个原因
标题必须和数据行名称一致,如 数据行列名为:num ,标题行必须为 num_t 才可以