这题其实和 NIKKEI 2019-2-D Shortest Path on a Line 差不多的啦,都是一种最短路的变形,把多个点和边关联了起来。

题面

你要从一楼到 \(n\) 楼去,每层楼可以选择坐电梯和走楼梯,第 \(i\) 和 \(i+1\) 层之间的楼梯花费 \(a_i\) 时间,而电梯花费 \(b_i\) 时间,而且进出电梯有个时间成本 \(c\)。

那么显然,从 \(x\) 楼到 \(y\) 楼走楼梯的花费是 \(\sum\limits_{i=min(x, y)}^{max(x, y) - 1} a_i\),坐电梯的花费是 \(c + \sum\limits_{i=min(x, y)}^{max(x, y) - 1} b_i\)(这里直接把 CF 上面的式子抄过来了)。

题解

首先有以下结论:

(1) 从底到顶的最短距离是单调递增的

因为整个上楼的操作是连续的,假如有一个从一楼到 \(p_2\) 楼的最短路比一楼到 \(p_1\) 楼的最短路要短(其中 \(p_1<p_2\)),那么就逆推回去(注意此处不是坐电梯或走楼梯下楼,是逆推),就变成了从 \(p_2\) 上减去一定的时间,显然此时一定会比 \(p_2\) 小。

(2) 到达每层楼的最短路径长度不需要从比它高的楼推出

结论 (1) 中为了证明单调递增,使用了从楼上推回楼下的做法,实际操作中并没有必要,因为由单调递增可知如果是从楼上再下来(不是逆推)必定比楼下上来时间长,因此结论得证。

由以上结论可以得到一个解法,即用线段树维护下面各层楼到这层楼坐电梯和走路的时间加上一楼到该层楼的时间,然后在每层楼选取一个最优的方案上来即可,注意储存坐电梯上来时的花费减去 \(c\),防止多段连续的电梯乘坐。

代码

#include<cstdio>
#include<algorithm>
#define ls pos<<1
#define rs (pos<<1)+1
#define MID (tree[pos].l+tree[pos].r)>>1
const int MAXN=2e5+5;
struct Tree{int l,r;long long val,lazy;};
int n,c;long long s[MAXN],e[MAXN];
struct SegTree
{
Tree tree[MAXN*4];
void BuildTree(int l,int r,int pos)
{
tree[pos].l=l;tree[pos].r=r;tree[pos].val=4e9+7;
if(l==r) return;
int mid=MID;
BuildTree(l,mid,ls);BuildTree(mid+1,r,rs);
}
void DownReload(int pos)
{
if(tree[pos].lazy)
{
tree[ls].lazy+=tree[pos].lazy;
tree[rs].lazy+=tree[pos].lazy;
tree[ls].val+=tree[pos].lazy;
tree[rs].val+=tree[pos].lazy;
tree[pos].lazy=0;
return;
}
}
void UpReload(int pos){tree[pos].val=std::min(tree[ls].val,tree[rs].val);}
void SegUpdate(int l,int r,long long delta,int pos)//ADD value
{
if(l<=tree[pos].l&&r>=tree[pos].r)
{
tree[pos].val+=delta;
tree[pos].lazy+=delta;
return;
}
DownReload(pos);
int mid=MID;
if(r<=mid) SegUpdate(l,r,delta,ls); else if(l>mid) SegUpdate(l,r,delta,rs); else {SegUpdate(l,mid,delta,ls);SegUpdate(mid+1,r,delta,rs);}
UpReload(pos);
}
void PtUpdate(int target,long long delta,int pos)//SET value
{
if(tree[pos].l==tree[pos].r)
{
tree[pos].val=delta;
return;
}
DownReload(pos);
int mid=MID;
if(target<=mid) PtUpdate(target,delta,ls); else PtUpdate(target,delta,rs);
UpReload(pos);
}
long long Query(int l,int r,int pos)
{
if(l==tree[pos].l&&r==tree[pos].r) return tree[pos].val;
DownReload(pos);
int mid=MID;
if(r<=mid) return Query(l,r,ls); else if(l>mid) return Query(l,r,rs); else return std::min(Query(l,mid,ls),Query(mid+1,r,rs));
}
};
SegTree elv,stair;
int main()
{
scanf("%d %d",&n,&c);
for(int i=2;i<=n;i++)
scanf("%lld",&s[i]);
for(int i=2;i<=n;i++)
scanf("%lld",&e[i]);
printf("0 ");
elv.BuildTree(1,n,1);
stair.BuildTree(1,n,1);
elv.PtUpdate(1,0,1);
stair.PtUpdate(1,0,1);
long long re,rstr,min;
for(int i=2;i<=n;i++)
{
elv.SegUpdate(1,i-1,e[i],1);
re=elv.Query(1,i-1,1)+c;
stair.SegUpdate(1,i-1,s[i],1);
rstr=stair.Query(1,i-1,1);
if(re<rstr)
{
elv.PtUpdate(i,re-c,1);
stair.PtUpdate(i,re,1);
printf("%lld ",re);
}
else
{
elv.PtUpdate(i,rstr,1);
stair.PtUpdate(i,rstr,1);
printf("%lld ",rstr);
}
}
return 0;
}

Codeforces 1249E By Elevator or Stairs? 题解的更多相关文章

  1. [题解]Mail.Ru Cup 2018 Round 1 - A. Elevator or Stairs?

    [题目] A. Elevator or Stairs? [描述] Masha要从第x层楼去第y层楼找Egor,可以选择爬楼梯或者坐直升电梯.已知爬楼梯每层需要时间t1:坐直升电梯每层需要时间t2,直升 ...

  2. # Codeforces Round #529(Div.3)个人题解

    Codeforces Round #529(Div.3)个人题解 前言: 闲来无事补了前天的cf,想着最近刷题有点点怠惰,就直接一场cf一场cf的刷算了,以后的题解也都会以每场的形式写出来 A. Re ...

  3. Codeforces 547C/548E - Mike and Foam 题解

    目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...

  4. Codeforces Round #557 (Div. 1) 简要题解

    Codeforces Round #557 (Div. 1) 简要题解 codeforces A. Hide and Seek 枚举起始位置\(a\),如果\(a\)未在序列中出现,则对答案有\(2\ ...

  5. Codeforces Round #665 (Div. 2)A-C题解

    A. Distance and Axis 题目:http://codeforces.com/contest/1401/problem/A 题解:对于n来说分两种情况,一是奇数,二则是偶数 ①奇数:对于 ...

  6. Codeforces Round #668 (Div. 2)A-C题解

    A. Permutation Forgery 题目:http://codeforces.com/contest/1405/problem/A 题解:这道题初看有点吓人,一开始居然想到要用全排序,没错我 ...

  7. Codeforces Round #669 (Div. 2)A-C题解

    A. Ahahahahahahahaha 题目:http://codeforces.com/contest/1407/problem/A 题解:最多进行n/2的操作次数,我们统计这n个数中1的个数,是 ...

  8. Codeforces GYM 100876 J - Buying roads 题解

    Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...

  9. Codeforces 983C Elevator dp (看题解)

    Elevator 怎么今天写啥题都不会写啊, 我是傻了吗.. 把电梯里面四个人的目标点当作状态, 然后暴力转移. #include<bits/stdc++.h> #define LL lo ...

随机推荐

  1. 【Python与线程】

    "   目录 一.全局解释器锁GIL 二.Python线程模块的选择 三.线程的创建 三.锁机制 四.信号量 五.事件 六.条件 七.定时器 八.线程队列 九.线程池 补充:线程安全 imp ...

  2. Vue.js开发去哪儿网WebApp

    一.项目介绍 这个项目主要参考了去哪儿网的布局,完成了首页.城市选择页面.详情页面的开发. 首页:实现了多区域轮播的功能,以及多区域列表的展示: 城市选择页面:在这个页面实现了城市展示.城市搜索.城市 ...

  3. AOP的基本认识

    一.AOP的概念 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善. ...

  4. pip配置永久国内源

    1.windows配置方式: (1)打开文件资源管理器 --------在地址栏中输入 %appdata% (2)手动创建一个文件夹叫做 pip (3)在pip的文件夹里面新建一个文件 pip.ini ...

  5. maven的背景

    本书链接 链接:http://pan.baidu.com/s/1c2fF3Ks 密码:hlce maven是一套软件工程管理和整合工具. 基于工程对象模型的概念(POM),通过一个中央信息管理模块,m ...

  6. 【代码审计】VAuditDemo 命令注入漏洞

    一般PHP中可以使用下列函数来执行外部的应用程序或命令 system() exec() passthru() shell_exec() 跟踪$cmd --> 跟进$target,发现传递给tar ...

  7. 23 JavaScript规范与最佳实践&性能&箭头函数

    大多数web服务器(Apache等)对大小写敏感,因此命名注意大小写 不要声明字符串.数字和布尔值,始终把他们看做原始值而非对象,如果把这些声明为对象,会拖慢执行速度 对象是无法比较的,原始值可以 不 ...

  8. 第3章 Java基本的程序设计结构

    3.运算符 浅谈java中源码常见的几个关键字(native,strictfp,transient,volatile) 需要注意 , 整数被 0 除将会产生一个异常, 而浮点数被0 除将会得到无穷大或 ...

  9. 代理模式之静态代理,JDK动态代理和cglib动态代理

    代理模式,顾名思义,就是通过代理去完成某些功能.比如,你需要购买火车票,不想跑那么远到火车站售票窗口买,可以去附近的火车票代售点买,或者到携程等第三方网站买.这个时候,我们就把火车站叫做目标对象或者委 ...

  10. 0X01应用程序黑客技术

    前言 该文章主要是讲解了常见的应用程序黑客技术基本概念,包括消息钩取,API钩取,DLL注入,代码注入 天象独行 0X01:消息钩取 原理:在我们通过键盘,鼠标等输入信息过程中,Windows会通过钩 ...