Codeforces 1249E By Elevator or Stairs? 题解
这题其实和 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? 题解的更多相关文章
- [题解]Mail.Ru Cup 2018 Round 1 - A. Elevator or Stairs?
[题目] A. Elevator or Stairs? [描述] Masha要从第x层楼去第y层楼找Egor,可以选择爬楼梯或者坐直升电梯.已知爬楼梯每层需要时间t1:坐直升电梯每层需要时间t2,直升 ...
- # Codeforces Round #529(Div.3)个人题解
Codeforces Round #529(Div.3)个人题解 前言: 闲来无事补了前天的cf,想着最近刷题有点点怠惰,就直接一场cf一场cf的刷算了,以后的题解也都会以每场的形式写出来 A. Re ...
- Codeforces 547C/548E - Mike and Foam 题解
目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...
- Codeforces Round #557 (Div. 1) 简要题解
Codeforces Round #557 (Div. 1) 简要题解 codeforces A. Hide and Seek 枚举起始位置\(a\),如果\(a\)未在序列中出现,则对答案有\(2\ ...
- Codeforces Round #665 (Div. 2)A-C题解
A. Distance and Axis 题目:http://codeforces.com/contest/1401/problem/A 题解:对于n来说分两种情况,一是奇数,二则是偶数 ①奇数:对于 ...
- Codeforces Round #668 (Div. 2)A-C题解
A. Permutation Forgery 题目:http://codeforces.com/contest/1405/problem/A 题解:这道题初看有点吓人,一开始居然想到要用全排序,没错我 ...
- Codeforces Round #669 (Div. 2)A-C题解
A. Ahahahahahahahaha 题目:http://codeforces.com/contest/1407/problem/A 题解:最多进行n/2的操作次数,我们统计这n个数中1的个数,是 ...
- Codeforces GYM 100876 J - Buying roads 题解
Codeforces GYM 100876 J - Buying roads 题解 才不是因为有了图床来测试一下呢,哼( 题意 给你\(N\)个点,\(M\)条带权边的无向图,选出\(K\)条边,使得 ...
- Codeforces 983C Elevator dp (看题解)
Elevator 怎么今天写啥题都不会写啊, 我是傻了吗.. 把电梯里面四个人的目标点当作状态, 然后暴力转移. #include<bits/stdc++.h> #define LL lo ...
随机推荐
- Jmeter_选项_函数助手_RandomString的用法
1.用处:测试账户注册可以通过随机生成数实现,而不需要Excel手动输入, 缺点:随机生成数可能会重复 优点:不需要使用CSV config 或者excel ,txt格式 2.举例:之前我们通过CSV ...
- 消息队列(五) ---RocketMQ-消息存储3
问题: consumeQueue 如何工作 刷盘机制如何工作 概述 该节我们将学习 consumeQueue 如何工作,先来看一下消息发送的大概过程. 而为什么需要 consumeQueue 的存在呢 ...
- oracle 多表查询,请教个问题
首先,是有一个合同表,对应数据库表 lg_bill_of_lading_detail 简称 bold 有一个用户表 EMT_USER 简称 e 合同审批 后,合同表里 会有一个审核人AUDI ...
- SpringBoot2.x整合Shiro出现cors跨域问题(踩坑记录)
1. Springboot如何跨域? 最简单的方法是: 定义一个配置CorsConfig类即可(是不是简单且无耦合到令人发指) @Configuration public class CorsConf ...
- C# 抗变与协变的理解
我们知道 方法的参数是协变的: void display(shape o) 如果类Rectangle 继承于shape类,那我们可以给该方法传入Rectangle类的实例. 而方法的返回类型是抗变的, ...
- C#加密解密(AES)-AESHelper
原文地址:https://ken.io/note/csharp-aesencrypt using System; namespace Encrypt { public class AESHelper ...
- oracle学习笔记(十四) 数据库对象 索引 视图 序列 同义词
数据库对象 用户模式:指数据库用户所创建和存储数据对象的统称.在访问其它用户模式的数据库对象时需加上用户模式. 如:scott.emp, scott.dept等. 数据库对象包括:表.视图.索引.序列 ...
- ES6:字面量的增强写法
以前对象字面量的写法: 属性的增强写法: ES6中可以写成: 方法的增强写法 ES6中可以写成: ~~~~~ END ~~~~~
- windows 删除进程
win+R打开doc窗口 netstat -ano |findstr "8888" tskill 10120 结束进程
- springboot @Select @Insert @Update @Delete
https://blog.csdn.net/qq_20867981/article/details/80641353 使用@Select.@Insert.@Update.@Delete注解代替xxxM ...