这题其实和 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. C++中map的介绍用法以及Gym题目:Two Sequences

    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字(key),每个关键字只能在map中出现一次,第二个可能称为该关键字的值(value))的数据 处理能力,由于这个特性,它完成有可能 ...

  2. 蚁人cp数

    可怜的蚁人进入量子领域后,黄蜂女被灭霸的一个响指带走,导致可怜的蚁人困在了量子领域,为了生存,他们开始建造自己家园. 蚁人为了方便在这里生存,他们建造了自己火车站.某车站有N个人上车,其中M对是情侣, ...

  3. 四级技能修炼NPC脚本参考

    [@main] #act CloseBigDialogBox #say \ \ <本服推出部分四级技能.升级四级技能很简单./SCOLOR=250>\ \ <只需要1个/SCOLOR ...

  4. SpringCloud全家桶学习之一阶段总结(一)

    一.概述 前几篇小博客记录了我学习SpringCloud组件的过程,并与工作中所用的Dubbo框架做了一点比较,基本组件:Eureka.Ribbon.Hystrix.Feign.Zuul.Config ...

  5. 基于G6画个xmind出来

    公司产品因为业务发展,出现了一个新的需求:需要去实现知识库的层级知识展示,展示效果通过树图来实现,具体的展示形式可见下图: 其中有几个需要注意点: 节点上的详情icon可以点击,点击展开关闭详情 节点 ...

  6. Python版GPA计算器

    最近在网申投简历时遇到一个需要计算GPA的问题,想起自己在上学时写的Excel公式版GPA计算器略显low,而且操作也比较复杂,于是一时兴起,写了个Python版的,在此分享给大家,也算是跟上时代的浪 ...

  7. mybatis源码探索笔记-2(构建SqlSession并获取代理mapper)

    前言 上篇笔记我们成功的装载了Configuration,并写入了我们全部需要的信息.根据这个Configuration创建了DefaultSqlSessionFactory.本篇我们实现构建SqlS ...

  8. 高级T-SQL进阶系列 (二)【上篇】:使用 APPLY操作符

    [译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正] 原文链接:传送门. 伴随着SQL SERVER 2005的发布,微软增加了一个新的操作符,它允许你将一个记录集与一个函数进行关联,然 ...

  9. 【JavaWeb】导入Excel并进行校验

    一.需要实现的目标 1.界面编写 2.导入表读取表名,进行校验,后台匹配(判断此表的名称是否能够模糊匹配上) 3.确定表存在,读取其中的数据,暂存 4.正则表达式数据校验(判断是否已存在,数据是否符合 ...

  10. springBoot+MybatisPlus数据库字段使用驼峰命名法时报错

    假如有个实体类: package com.jeff.entity; public class User { /** * 主键id */ private Integer id; /** * 登陆名 */ ...