模拟考最后一题是这道题,要是数组开大就场切了,最后不小心挂了 \(15\) 分。

以下是考场思路:

考虑这样一个问题,所有时间对 \(r+g\) 取余是可以的。毕竟红绿灯是一个循环。

再考虑这样一个东西,等过一次红灯后的所有情况是相似的,从循环的角度出发都是时刻 \(0\)。

因此考虑处理出出发之后第一次遇到红绿灯的点,然后问题就变成从一个路口到终点,可以使用一次 \(n^2\) 的 dp 完成。

接下来先考虑如何处理第一次遇到红绿灯的点。

假若需要从之前的路口走到这个路口需要花费时间 \(x\) 那么满足以下条件的出发时间 可能 会在这个点第一次遇到红绿灯。

\[t + x < g (\bmod (r+g))
\]

第一次遇到红绿灯的点就是最小的 \(x\)。

实际上满足条件的 \(t\) 根据与 \(g\) 的大小关系构成至多两段区间,考虑动态开点权值线段树维护区间取最小值和单点查询。

接下来考虑如何优化上面那个 \(n^2\) 的 dp 我们可以发现等完红绿灯出发与从起点出发的情况实际上是类似的,倒着扫描一遍且与上面那种情况类似的用线段树维护即可。

注意空间不要开小了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+114;
const int inf = 1e9+114;
int tr[maxn*70+1],tag[maxn*70+1],ls[maxn*70+1],rs[maxn*70+1],tot;
long long l[maxn],pre[maxn],dp[maxn];
long long cost[maxn];
long long G,R,n,q;
void pushdown(long long cur){
if(ls[cur]==0) ls[cur]=++tot;
if(rs[cur]==0) rs[cur]=++tot;
tr[ls[cur]]=min(tr[ls[cur]],tag[cur]);
tr[rs[cur]]=min(tr[rs[cur]],tag[cur]);
tag[ls[cur]]=min(tag[ls[cur]],tag[cur]);
tag[rs[cur]]=min(tag[rs[cur]],tag[cur]);
tag[cur]=inf;
}
void pushup(long long cur){
tr[cur]=min(tr[ls[cur]],tr[rs[cur]]);
}
void update(int &cur,long long lt,long long rt,long long l,long long r,int v){
if(lt>rt) return ;
if(l>rt||r<lt) return;
if(cur==0) cur=++tot;
if(l<=lt&&rt<=r){
tr[cur]=min(tr[cur],v);
tag[cur]=min(tag[cur],v);
return ;
}
long long mid=(lt+rt-1)>>1;
pushdown(cur);
update(ls[cur],lt,mid,l,r,v);
update(rs[cur],mid+1,rt,l,r,v);
pushup(cur);
}
long long query(long long cur,long long lt,long long rt,long long l,long long r){
if(l>rt||r<lt||cur==0) return inf;
if(l<=lt&&rt<=r) return tr[cur];
long long mid=(lt+rt-1)>>1;
pushdown(cur);
return min(query(ls[cur],lt,mid,l,r),query(rs[cur],mid+1,rt,l,r));
}
int rt;
void init(){
for(long long i=1;i<=n;i++) pre[i]=(pre[i-1]+l[i])%(G+R),cost[i]=cost[i-1]+l[i];
for(long long i=0;i<maxn*70;i++) tr[i]=tag[i]=inf;
dp[n+1]=0;
for(int i=n;i>=1;i--){
long long x=(G+R-pre[i])%(G+R);
long long y=query(rt,0,G+R-1,(x)%(G+R),(x)%(G+R));
if(y<inf) dp[i]=dp[y]+(cost[y]-cost[i]+((G+R)-((cost[y]-cost[i])%(G+R))));
else dp[i]=cost[n]-cost[i]+l[n+1];
if(pre[i]<=G){
update(rt,0,G+R-1,G-pre[i],R+G-1-pre[i],i);
}
else{
update(rt,0,G+R-1,0,R+G-1-pre[i],i);
update(rt,0,R+G-1,G+R-pre[i]+G,R+G-1,i);
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>G>>R;
for(long long i=1;i<=n+1;i++) cin>>l[i];
init();
cin>>q;
while(q--){
long long x;
cin>>x;
long long st=query(rt,0,G+R-1,x%(G+R),x%(G+R));
if(st==inf){
cout<<x+cost[n]+l[n+1]<<'\n';
}
else{
long long res=cost[st]+x+((G+R)-((cost[st]+x)%(G+R)));
res+=dp[st];
cout<<res<<'\n';
}
}
return 0;
}
/*
4 5 1
12 18 4 6 7
5
4
11
5
3
2
*/

CF187D 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. 更新Homebrew时候遇到的问题

    问题描述: 更新Homebrew时候遇到无法访问github的问题,判定原因为DNS污Ran. fatal: unable to access 'https://github.com/Homebrew ...

  2. Cesium教程10-把影像和天空改成背景图片

    在使用Cesium引擎时,我们经常要使用大屏适配导致地球或者模型的黑色天空盒和大屏的样式不匹配造成场景不好看的情况,这样就可以用到我们修改Cesium的天空为纯色背景,与大屏更适配,直接上代码. &l ...

  3. VNC远程控制软件是什么?有没有更好的远程桌面控制解决方案?

    看官老爷们,你们是否需要远程访问或远程支持解决方案?来了解下VNC吧. 什么是VNC? VNC是虚拟网络计算(VNC)是一种远程桌面共享技术,用于从世界任何地方远程访问和控制计算机. VNC的工作原理 ...

  4. 如何将 iPad 用作 Windows 计算机的第二台显示器?

    安装第二台显示器是扩大屏幕空间的一种常用方法.如果您偶尔只需要第二个显示器(例如您偶尔在家中工作),但又不想购买整个第二个显示器,则可以将 iPad 用作廉价的替代品. 要将 iPad 用作Windo ...

  5. C++ 初始化列表(Initialization List)

    请注意以下继承体系中各class的constructors写法: 1 class CPoint 2 { 3 public: 4 CPoint(float x=0.0) 5 :_x(x){} 6 7 f ...

  6. SimpleHTTPServer模块详解

    SimpleHTTPServer实现文件的展示和下载 可以用python2.7直接启动一个进程.以命令执行的当前目录为页面根目录,如果不存在index.html,默认展示当前目录的所有文件. pyth ...

  7. linux 自定义程序开机自启

    实现开机自启常见的有两种方法: /etc/init.d/下编写脚本命令(有些机子会有问题,比较麻烦) 利用定时任务crontab 本文介绍crontab现实程序开机自启 编写执行脚本run.sh #! ...

  8. gin+MySQL简单实现数据库查询

    利用 gin 项目搭建一个简易的后端系统. 一个简易的 HTTP 响应接口 首先在 go 工作区的终端输入这条指令: go get -u github.com/gin-gonic/gin 将 gin ...

  9. WPF 实现触摸滑动功能

    自定义ScrollViewer的Touch事件--触摸上下移动ScrollViewer滚动到指定位置   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...

  10. linux下 IPv6组播(C++)

      Server #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <s ...