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 ...
随机推荐
- SPAN, RSPAN, ERSPAN
该文档摘自:Home > CCIE Routing and Switching Study Group > Discussions 由 Deben 于 2015-2-6 上午6:50 创建 ...
- IIS-代理
http://192.168.11.3:8083/java 访问 http://192.168.11.3:8089 http://192.168.11.3:8083/?id=1 访问http:/ ...
- 怎么拆分一个Excel工作簿中的多个工作表?
打开需要编辑的Excel文档.如图所示,工作簿下方有很多工作表.现在需要将这些工作表单独拆分开成一个个工作簿. 右键任意一个工作表标签,在弹出的下拉列表中选择查看代码.即弹出代码窗口.如下图所示. ...
- LeetCode练题——70. Climbing Stairs
1.题目 70. Climbing Stairs——Easy You are climbing a stair case. It takes n steps to reach to the top. ...
- JavaScirpt - 模块的写法
传送门 http://www.ruanyifeng.com/blog/2012/10/javascript_module.html 1. 原始写法 function f1() { // do sth. ...
- 例题3_2 WERTYU(UVa10082)
把手放在键盘上时,稍不注意就会往右错一位.这样,输入Q会变成W,输入J会变成K等.键盘如下图所示: 输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子.输入保证合法,即一定是错位 ...
- PyQt5复杂控件(树控件、选项卡控件(滚动条控件、多文档控件、停靠控件)
1.树控件的基本使用方法QTreeWidget'''QTreeWidget树控件的使用方法添加图标,添加表格,添加复选框等'''from PyQt5.QtWidgets import *from Py ...
- js HTML 年月日星期 时间的
效果格式:2019 年 04 月 13 日 星期六 13 : 24 : 49上面的类名有多余的 因为这是之前项目中的 方便以后使用 <!DOCTYPE html> <html> ...
- C#多个泛型约束问题
多个约束之间使用逗号隔开,但不重复T约束. 1. private void AddControl<T>(TabPage tabPage, T userControl) where T: U ...
- 使用docker构建第一个spring boot项目
在看了一些简单的docker命令之后 打算自己尝试整合一下docker+spring boot项目本文是自己使用docker+spring boot 发布一个项目1.docker介绍 docke是提供 ...