P1081 [NOIP 2012 提高组] 开车旅行 题解
前言
爆肝到半夜,中间假了一次,最终调过了两个样例,交上去过了。
题解
思路
首先进行预处理。
用一种你喜欢的数据结构维护每个城市的海拔,容易求出从每个城市出发,小 \(A\) 和小 \(B\) 开一天能到达的城市。
因为小 \(A\) 开一天,小 \(B\) 开一天,所以设每两天为一个周期。用一个倍增数组 \(f_{i,j}\) 维护从第 \(i\) 个城市出发,行驶 \(2^j\) 个周期,能到达的城市,用数组维护这段路程的长度、小 \(A\) 开的路程和小 \(B\) 开的路程。
对于第一个问题,我们枚举每一个城市,通过求出从这里出发所能到达最远的城市,即可得到小 \(A\) 和小 \(B\) 分别行驶的路程,就能在 \(O(n\log{n})\) 的时间内得到答案。
对于第二个问题,我们仿照上一问直接求解,时间复杂度 \(O(m\log{n})\)。
实现
关于预处理,由于海拔各不相同,所以可选的数据结构较多。笔者使用 vector,每次用 lower_bound 查找,倒着扫一遍就出来了。
因为要求第二近的,所以在需要在 vector 中遍历每个城市前后两个城市的海拔。
关于求解,需要注意,可能真正最远的城市不一定是通过 \(f_{i,j}\) 数组求出的城市,需要判断能不能让小 \(A\) 再走一天。
剩下的细节看代码。
代码
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define N 100005
#define abs(x) ((x)>0?(x):-(x))
int n,m,a[N];
std::vector<int> vc;
int d[N],sd[N];
int f[N][22],g[N][22],ga[N][22],gb[N][22];
int dis(int x,int y)
{
if(x==-1||y==-1) return 1e9;
return abs(a[x]-a[y]);
}
int li[N],b[N];
bool cmp(int x,int y) {return a[x]<a[y];}
void dmin(int k,int l,int r)
{
int mi=-1;
if(l<0) l=0;
if(r>=vc.size()) r=vc.size()-1;
for(int i=l;i<=r;i++)
if(mi==-1||dis(k,li[vc[i]])<dis(k,mi)) mi=li[vc[i]];
if(mi==-1) {d[k]=sd[k]=-1;return;}
d[k]=mi;int mi2c=-1;
for(int i=l;i<=r;i++) if(li[vc[i]]!=mi&&(mi2c==-1||dis(k,li[vc[i]])<dis(k,mi2c))) mi2c=li[vc[i]];
if(mi2c==-1) sd[k]=-1;
else sd[k]=mi2c;
}
void getd()
{
for(int i=1;i<=n;i++) li[i]=i;
std::sort(li+1,li+n+1,cmp);
for(int i=1;i<=n;i++) b[li[i]]=i;
for(int i=n;i>=1;i--)
{
if(i<n)
{
int pos=lower_bound(vc.begin(),vc.end(),b[i])-vc.begin()-1;
dmin(i,pos-1,pos+3);
}
vc.insert(lower_bound(vc.begin(),vc.end(),b[i]),b[i]);
}
d[n]=-1,sd[n]=sd[n-1]=-1;
}
int main()
{
memset(f,0,sizeof(f));
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
getd();
for(int i=1;i<=n;i++)
{
if(sd[i]!=-1) f[i][0]=d[sd[i]];
else f[i][0]=-1;
ga[i][0]=dis(i,sd[i]);
gb[i][0]=dis(sd[i],d[sd[i]]);
g[i][0]=ga[i][0]+gb[i][0];
}
for(int i=1;(1<<i-1)<=n;i++) for(int j=1;j<=n;j++)
{
if(f[j][i-1]!=-1)
{
f[j][i]=f[f[j][i-1]][i-1];
g[j][i]=g[j][i-1]+g[f[j][i-1]][i-1];
ga[j][i]=ga[j][i-1]+ga[f[j][i-1]][i-1];
gb[j][i]=gb[j][i-1]+gb[f[j][i-1]][i-1];
}
else
{
f[j][i]=-1;
g[j][i]=ga[j][i]=gb[j][i]=1e9;
}
}
int x0;
scanf("%d",&x0);
int ma=1e9,mb=1,mi=-1;
for(int i=1;i<=n;i++)
{
int s=i,sum=0,sa=0,sb=0;
for(int j=20;j>=0;j--) if(f[s][j]>0&&sum+g[s][j]<=x0)
sum+=g[s][j],sa+=ga[s][j],sb+=gb[s][j],s=f[s][j];
if(s<n-1&&sum+dis(s,sd[s])<=x0) sa+=dis(s,sd[s]);
if(mi==-1||1ll*ma*sb>1ll*mb*sa) ma=sa,mb=sb,mi=i;
if((sb||mi==-1)&&1ll*ma*sb==1ll*mb*sa&&a[i]>a[mi]) mi=i;
}
printf("%d\n",mi);
scanf("%d",&m);
while(m--)
{
int s,x;
scanf("%d%d",&s,&x);
int sum=0,sa=0,sb=0;
for(int j=20;j>=0;j--) if(f[s][j]>0&&sum+g[s][j]<=x)
sum+=g[s][j],sa+=ga[s][j],sb+=gb[s][j],s=f[s][j];
if(s<n-1&&sum+dis(s,sd[s])<=x) sa+=dis(s,sd[s]);
printf("%d %d\n",sa,sb);
}
}
\]
P1081 [NOIP 2012 提高组] 开车旅行 题解的更多相关文章
- noip 2012 提高组 day2 部分题解
这道题有多种解法,我用的是扩展欧几里得算法求到的答案 #include<iostream> #include<fstream> #include<cstdio> u ...
- [NOIP2012提高组]开车旅行
题目:洛谷P1081.Vijos P1780.codevs1199. 题目大意:有n座海拔高度不相同的城市(编号1~n),两城市的距离就是两城市海拔之差.规定每次只能从编号小的城市走到编号大的城市. ...
- noip 2013 提高组 Day2 部分题解
积木大赛: 之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是2组超时 先把暴力程序贴上来(可以当对拍机) #include<iostream> #incl ...
- Vigenère 密码NOIP 2012 提高组 第一天 第一题
题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南 ...
- NOIP 2001 提高组 题解
NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...
- NOIP 2008提高组第三题题解by rLq
啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...
- NOIP 2014 提高组 题解
NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...
- 最优贸易 NOIP 2009 提高组 第三题
题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行
[NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...
- noip 2014 提高组初赛
noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...
随机推荐
- PTA-1002
原先主要错误: 没有考虑到有关0的相关情况 观看的大佬代码 整理思路 无非就是在相同的指数的情况下,系数相加 因为最后是要从大到小输出来. 注意 要对最后的结果进行四舍五入: PTA的英语题对英语不好 ...
- 在Windows下为CodeBlocks20.3安装、配置wxWidget3.2.6
0.前言 CodeBlocks是使用C++编写程序的一个很好的开发环境,最大的好处是它是开源的.免费的,而不仅仅是因为它具有跨平台的能力.还有一个很重要的原因是在CodeBlocks中可以使用wxWi ...
- 史上最牛X的微信公众号!
今天给大家推荐一个最牛逼的微信公众号,专注分享技术干货,包括但不限于Java,HTML,JavaScript,MySQL,Redis,Windows,Linux,Spring,SpringBoot,V ...
- Flutter 滑动组件互相嵌套问题
滑动组件互相嵌套问题 如果listview/singlechildscrollview 嵌套gridview,将两个组件的shrinkwrap设置为true,并且gridview无法滚动 physic ...
- .NET 6 探索 Minimal API 系列
今天看到来自 https://www.dotnetdeveloper.cn/ 的一个 .NET 6 Minimal API 系列,感觉质量不错,特别收录在这里. .Net 6探索 (1) Minima ...
- GienTech动态|入选软件和信息技术服务名牌企业;荣获城市数字化转型优秀案例;参加第四届深圳国际人工智能展
中电金信入选"2023第二届软件和信息技术服务名牌企业" 近日,中国电子信息行业联合会发布了"2023第二届软件和信息技术服务名牌企业"名单,中电金信入 ...
- apache kylin的一些注意事项(解决kylin报错Storage schema reading not supported)
1.目前我所使用的kylin版本为2.6.2,有时在完成一次构建后会出现fail to locate kylin.properties的异常,如图所示 经排查,定位到kylin源码中的 org.apa ...
- 关于Jetson nano (B02)如何部署Yolov8以及一些必要的知识点
一.前言 记录一个简单的安装和部署过程,尽管笔者也是按照教程来的,但奈何参考了很多教程,虽然写的都非常好,但是却很散,因此笔者这里想把这些教程的精华提炼出来,汇总并且写在正文处.还是老规矩,笔者也在学 ...
- Qt/C++编写物联网组件/支持modbus/rtu/tcp/udp/websocket/mqtt/多线程采集
一.功能特点 支持多种协议,包括Modbus_Rtu_Com/Modbus_Rtu_Tcp/Modbus_Rtu_Udp/Modbus_Rtu_Web/Modbus_Tcp/Modbus_Udp/Mo ...
- Qt编写视频监控系统77-Onvif组件支持非正常时间的设备
一.前言 在经历了大量的现场设备测试,至少几十种厂家.几百种设备,遇见过奇奇怪怪的问题,一个个想方设法解决,发现有个问题是在下发鉴权的时候,需要带上设备的时间,而不是发送端的时间,如果带的不是设备上的 ...