LG1081 开车旅行
题意
城市\(i\)的海拔高度为\(H_i\)(各不相同)。定义距离为海拔差的绝对值
小\(A\)和小\(B\)轮流开车。从\(S\)起,一直向东行驶。
小\(A\)会选择第二近的城市作为目的地。小\(B\)选择一个最近的城市作为目的地。(如果当前城市到两个城市的距离相同,则认为离海拔低的那个城市更近)。如果无法再开了,或者到达目的地会使行驶的总距离超出\(X\)公里,他们就会结束旅行。
单次询问:给定\(X\),问从哪个城市出发,小\(A\)行的路程与小\(B\)行的路程的比值最小
多次询问:给定\(S\)和\(X\),问小\(A\)行的路程与小\(B\)行的路程
\(1 \leq N \leq 10^5,1 \leq M \leq 10^5\)
思路
首先肯定要解决一个问题,小\(A\)和小\(B\)的目的地在哪里。
先排序,然后从第一个城市开始,比较\(i-1,i-2,i+1,i+2\)处距离。
很显然,由于是第一个点,这个时候找到的任何点一定在它东边。
同样的,找完第一个点后将第一个点删除,那么第二个点自然成为了第一个点,依次下去,便在\(O(n)\)的复杂度内完成了预处理。
接下来,就可以想到用倍增来解决。
用\(f[i][j]\)表示从\(j\)出发第\(2^i\)天到达的城市,发现除了\(i=0\)时是\(A\)在开其他都是\(B\)开,所以转移就很简单了\(f[i][j]=f[i-1][f[i-1][j]];\)
那么求出了路径,距离只要减一减就好了。
用\(g[i][j][0]\)表示从\(j\)出发第\(2^i\)天\(A\)开的,用\(g[i][j][1]\)表示从\(j\)出发第\(2^i\)天\(B\)开的,转移:
\(g[i][j][0]=g[i-1][j][0]+g[i-1][f[i-1][j]][0];\)
\(g[i][j][1]=g[i-1][j][1]+g[i-1][f[i-1][j]][1];\)
接下来的询问只要每次倍增凑距离就好了
对于第一个询问枚举出发点再比较
时间复杂度\(O((n+m)logn)\)
#include <bits/stdc++.h>
const int N=100005;
double INF=1000000000;
using std::sort;
int a[N],b[N],Next[N],last[N],c[N],n,m,f[21][N],x,ans=0,s;
long long h[N],suma,sumb,g[21][N][2];
bool cmp(int x,int y){
return h[x]<h[y];
}
int d(int x,int y){
return abs(h[x]-h[y]);
}
void solve(int x,int s){
for (int i=20;i>=0;i--)
if (g[i][s][0]+g[i][s][1]<=1ll*x){
x-=g[i][s][0]+g[i][s][1];
suma+=g[i][s][0];
sumb+=g[i][s][1];
if (s==f[i][s]) return;
s=f[i][s];
}
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld",&h[i]),c[i]=i;
h[0]=-200000000000;
sort(c+1,c+n+1,cmp);
for (int i=1;i<=n;i++) last[c[i]]=c[i-1],Next[c[i]]=c[i+1];
for (int i=1;i<=n;i++){
int x1=last[i],x2=last[x1],x3=Next[i],x4=Next[x3];
int dis1=abs(h[i]-h[x1]),dis2=abs(h[i]-h[x2]),dis3=abs(h[i]-h[x3]),dis4=abs(h[i]-h[x4]);
if (dis1<dis3 ||(dis1==dis3 && h[x1]<h[x3])) b[i]=x1; else b[i]=x3;
if (dis2<dis3 ||(dis2==dis3 && h[x2]<h[x3])) a[i]=x2;
else if (dis4<dis1 ||(dis4==dis1 && h[x4]<h[x1])) a[i]=x4;
else if (dis1<dis3 ||(dis1==dis3 && h[x1]<h[x3])) a[i]=x3;
else a[i]=x1;
if (a[i]==0) a[i]=i;
if (b[i]==0) b[i]=i;
last[Next[i]]=last[i],Next[last[i]]=Next[i];
}
for (int i=1;i<=n;i++){
f[0][i]=a[i];if (a[i]!=i) f[1][i]=b[a[i]];else f[1][i]=i;
g[0][i][0]=d(i,f[0][i]),g[1][i][0]=g[0][i][0];
if (a[i]!=i)g[1][i][1]=d(a[i],b[a[i]]);
}
for (int i=2;i<=20;i++)
for (int j=1;j<=n;j++){
f[i][j]=f[i-1][f[i-1][j]];
g[i][j][0]=g[i-1][j][0]+g[i-1][f[i-1][j]][0];
g[i][j][1]=g[i-1][j][1]+g[i-1][f[i-1][j]][1];
}
scanf("%d",&x);
double now=INF;
for (int i=1;i<=n-2;i++){
suma=0,sumb=0;
solve(x,i);
if (now==INF && sumb==0 && h[i]>h[ans]) ans=i;
if (sumb==0) continue;
if (suma*1.0/sumb<now ||(suma*1.0/sumb==now && h[i]>h[ans])){
now=suma*1.0/sumb;
ans=i;
}
}
printf("%d\n",ans);
scanf("%d",&m);
for (int i=1;i<=m;i++){
scanf("%d%d",&s,&x);
suma=0,sumb=0;
solve(x,s);
printf("%lld %lld\n",suma,sumb);
}
}
后记
要注意\(h[0]\)的初始化,原来没仔细看数据结果爆了\(4\)发
LG1081 开车旅行的更多相关文章
- Luogu 1081 【NOIP2012】开车旅行 (链表,倍增)
Luogu 1081 [NOIP2012]开车旅行 (链表,倍增) Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已 ...
- CH5701 开车旅行
题意 5701 开车旅行 0x50「动态规划」例题 描述 小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ...
- 2012Noip提高组Day1 T3 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- Cogs 1264. [NOIP2012] 开车旅行(70分 暴力)
1264. [NOIP2012] 开车旅行 ★★☆ 输入文件:drive.in 输出文件:drive.out 简单对比时间限制:2 s 内存限制:128 MB [题目描述] 小A 和小 ...
- 开车旅行 【NOIP2012 D1T3】
开车旅行 [NOIP2012 D1T3] 倍增 首先令\(a[i]\)表示从i出发最近的城市下标,\(b[i]\)表示从i出发第二近的城市下标 可以维护一个\(\text{set<pair< ...
- 洛谷 P1081 开车旅行(70)
P1081 开车旅行 题目描述 小AA 和小BB 决定利用假期外出旅行,他们将想去的城市从 11到 NN 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ii的海 ...
- 开车旅行 2012年NOIP全国联赛提高组(倍增+set)
开车旅行 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小A 和小B决定利用 ...
- [NOIP2012提高组]开车旅行
题目:洛谷P1081.Vijos P1780.codevs1199. 题目大意:有n座海拔高度不相同的城市(编号1~n),两城市的距离就是两城市海拔之差.规定每次只能从编号小的城市走到编号大的城市. ...
- P1081 [NOIP2012]开车旅行[倍增]
P1081 开车旅行 题面较为啰嗦.大概概括:一个数列,只能从一个点向后走,两种方案:A.走到和自己差的绝对值次小的点B.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...
随机推荐
- C++设计模式——状态模式
前言 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个状态下,都会有不同的行为.那么在代码中我们经常是这样实现的. typedef enum tagState { state, st ...
- Django ----- app 和 ORM的操作和介绍
创建APP ORM 介绍 ORM的操作 说明一下 GET 和 POST 的区别: , GET ①获取一个页面 ②提交数据 数据显示在URL ?user=alex&pwd=alexdsb ,PO ...
- 【原创】大叔经验分享(15)spark sql limit实现原理
之前讨论过hive中limit的实现,详见 https://www.cnblogs.com/barneywill/p/10109217.html下面看spark sql中limit的实现,首先看执行计 ...
- python之鼠标的操作
鼠标操作的方法,封装在ActionChains类中 perform:执行ActionChains中的所有存储行为 context_click:右键单击 move_to_element:悬停 doubl ...
- MySQL视图,函数,触发器,存储过程
1. 视图 视图是一个虚拟表,它的本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用[名称]即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的临时表摘出来, ...
- BeanPostProcessors (for example: not eligible for auto-proxying),报错解决
最近遇到个问题,springmvc项目debug启动失败 debug启动会卡住不动,run模式启动正常 debug启动输出到下面这行之后,就不会继续输出了 -- :: [INFO]- Bean 'da ...
- Golang 新手可能会踩的 50 个坑【转】
译文:https://github.com/wuYin/blog/blob/master/50-shades-of-golang-traps-gotchas-mistakes.md 原文:50 Sha ...
- git 回滚远程服务端master的代码
1.先备份版本 git checkout master git pull git branch master_backup //备份一下这个分支当前的情况 git push origin master ...
- python之验证码识别 特征向量提取和余弦相似性比较
0.目录 1.参考2.没事画个流程图3.完整代码4.改进方向 1.参考 https://en.wikipedia.org/wiki/Cosine_similarity https://zh.wikip ...
- SpringCloud使用Nacos服务发现实现远程调用
本文使用SpringCloud结合Nacos服务发现,Feign远程调用做一个简单的Demo. 1 Nacos 关于Nacos之前写了两篇文章关于SpringBoot对它的使用,感兴趣可以查看一下. ...