传送门

前言

爆肝到半夜,中间假了一次,最终调过了两个样例,交上去过了。

题解

思路

首先进行预处理。

用一种你喜欢的数据结构维护每个城市的海拔,容易求出从每个城市出发,小 \(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);
}
}

\[\Huge End
\]

P1081 [NOIP 2012 提高组] 开车旅行 题解的更多相关文章

  1. noip 2012 提高组 day2 部分题解

    这道题有多种解法,我用的是扩展欧几里得算法求到的答案 #include<iostream> #include<fstream> #include<cstdio> u ...

  2. [NOIP2012提高组]开车旅行

    题目:洛谷P1081.Vijos P1780.codevs1199. 题目大意:有n座海拔高度不相同的城市(编号1~n),两城市的距离就是两城市海拔之差.规定每次只能从编号小的城市走到编号大的城市. ...

  3. noip 2013 提高组 Day2 部分题解

    积木大赛: 之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是2组超时 先把暴力程序贴上来(可以当对拍机) #include<iostream> #incl ...

  4. Vigenère 密码NOIP 2012 提高组 第一天 第一题

    题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南 ...

  5. NOIP 2001 提高组 题解

    NOIP 2001 提高组 题解 No 1. 一元三次方程求解 https://vijos.org/p/1116 看见有人认真推导了求解公式,然后猥琐暴力过的同学们在一边偷笑~~~ 数据小 暴力枚举即 ...

  6. NOIP 2008提高组第三题题解by rLq

    啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...

  7. NOIP 2014 提高组 题解

    NOIP 2014 提高组 题解 No 1. 生活大爆炸版石头剪刀布 http://www.luogu.org/problem/show?pid=1328 这是道大水题,我都在想怎么会有人错了,没算法 ...

  8. 最优贸易 NOIP 2009 提高组 第三题

    题目描述 C 国有 n 个大城市和 m 条道路,每条道路连接这 n 个城市中的某两个城市.任意两个 城市之间最多只有一条道路直接相连.这 m 条道路中有一部分为单向通行的道路,一部分 为双向通行的道路 ...

  9. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  10. noip 2014 提高组初赛

    noip 2014 提高组初赛 一. TCP协议属于哪一层协议( ) A. 应用层 B. 传输层 C. 网络层 D. 数据链路层 B TCP(传输控制协议) 若有变量int a; float: x, ...

随机推荐

  1. php-fpm常见错误

    1. WARNING: Nothing matches the include pattern '/usr/local/php7/etc/php-fpm.d/*.conf' # cd /usr/loc ...

  2. pycharm之激活

    激活相关文件: https://github.com/lanlangdeai/develop-kit/tree/master/software/editor/pycharm 一. 激活码激活 步骤:  ...

  3. Litctf2024-郑州轻工业大学第二届ctf-校内赛道wp

    战队:怎落笔都不对 最终成绩校内第4 MISC 1. 盯帧珍珠 打开文件发现是一个图片,放入 010 查看得文件头是 gif 格式 改为gif后缀得到一个GIF图,在下面这个网站分解,即可得到flag ...

  4. Vue.js 数据绑定

    1.标签内容绑定 双括号语法:使用 {{}} 将变量包裹起来,vue会将变量的值解析为普通文本,而非 HTML 代码 <div>{{msg}}</div> <div> ...

  5. Vue.js 组件数据交互

    1.前言 本节讲述组件之间如何进行数据交互 2.props属性与非 prop 的属性 父组件通过属性绑定的形式传值给子组件,这种传值分2种 类别 含义 说明 props 子组件本身已经通过props定 ...

  6. fastadmin-表单使用

    1.日期时间 在FastAdmin中的日期时间组件采用的是Bootstrap-datetimepicker插件,官方文档:Bootstrap-datetimepicker官方教程 日期时间格式设置:设 ...

  7. 多段区间的时间滑块slider实现方式

    多段区间的时间滑块slider实现方式 写在前面:今天要实现一个尖峰平谷的数据配置,这可一下难倒我了,但是还好互联网上大神云集,感谢各位大神的倾情分享,现在就写下我的感悟,留给看到这篇文章的你 参考链 ...

  8. Pytest接口自动化测试框架Python自动化测试开发

    一.引言 在软件开发过程中,接口测试是确保软件各个组件之间数据传输和功能交互正常工作的重要环节.通过接口测试,可以提高软件的整体质量和稳定性.Pytest是一个流行的Python自动化测试框架,提供了 ...

  9. Flutter 引用包命名冲突,重复引用

    Flutter 引用包命名冲突,重复引用 报错信息 lib/page.dart:92:11: Error: 'Response' is imported from both 'package:get/ ...

  10. 使用PG的部分索引

    PG 又带来一个惊喜. 现在有一张表,每天增加几十万数据,数据量迅速超过 1亿.此时 create_at 上的索引已经非常庞大,检索速度很慢. 接下来要分表分区了? NO,PG 有一个非常有意思的特性 ...