洛谷 P1081 开车旅行
来源:互联网 发布:叉叉助手最新源码 编辑:程序博客网 时间:2024/05/01 11:12
题目描述
小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为Hi,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即d[i,j] = |Hi− Hj|。旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次。他们计划选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X 公里就结束旅行。小 A 和小 B的驾驶风格不同,小 B 总是沿着前进方向选择一个最近的城市作为目的地,而小 A 总是沿着前进方向选择第二近的城市作为目的地(注意:本题中如果当前城市到两个城市的距离相同,则认为离海拔低的那个城市更近)。如果其中任何一人无法按照自己的原则选择目的城市,或者到达目的地会使行驶的总距离超出 X 公里,他们就会结束旅行。
在启程之前,小 A 想知道两个问题:
1.对于一个给定的 X=X0,从哪一个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值最小(如果小 B 的行驶路程为 0,此时的比值可视为无穷大,且两个无穷大视为相等)。如果从多个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值都最小,则输出海拔最高的那个城市。
对任意给定的 X=Xi和出发城市 Si,小 A 开车行驶的路程总数以及小 B 行驶的路程
总数。
【题目分析】
倍增
【代码】
#include <set>#include <map>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const long long inf=1000000000000000000LL;const long double infd=1e60;set <long long> s;map <long long,long long> mp;struct node{long long h,dis;}t[5];long long h[100001],n,x0,q;long long a[100001],b[100001];long long fa[100001],fb[100001];long long va[100001][17],vb[100001][17];long long to[100001][17];long double ans1=1e60; long long st1;bool cmp(node a,node b){return (a.dis!=b.dis)?a.dis<b.dis:a.h<b.h;}void init(){ for (long long i=n;i>=1;--i) { s.insert(h[i]); t[1].h=*--s.lower_bound(h[i]); t[2].h=*s.upper_bound(h[i]); if (t[1].h!=-inf) t[3].h=*--s.lower_bound(t[1].h); else t[3].h=-inf; if (t[2].h!=inf) t[4].h=*s.upper_bound(t[2].h); else t[4].h=inf; for (long long j=1;j<=4;++j) t[j].dis=abs(h[i]-t[j].h); sort(t+1,t+5,cmp); a[i]=t[2].dis; fa[i]=mp[t[2].h]; b[i]=t[1].dis; fb[i]=mp[t[1].h]; for (long long j=0;j<=16;++j) { if (j==0) {if (fa[i]) {va[i][j]=a[i];to[i][j]=fa[i];}} else if (j==1) {if (fb[fa[i]]) {va[i][j]=a[i];vb[i][j]=b[fa[i]];to[i][j]=fb[fa[i]];}} else if (to[to[i][j-1]][j-1]) { va[i][j]=va[i][j-1]+va[to[i][j-1]][j-1]; vb[i][j]=vb[i][j-1]+vb[to[i][j-1]][j-1]; to[i][j]=to[to[i][j-1]][j-1]; } else break; } }}long double cal1(long long k,long long x){ long long ta=0,tb=0; for (long long i=16;i>=0;--i) { if (to[k][i]&&ta+va[k][i]+tb+vb[k][i]<=x) ta+=va[k][i],tb+=vb[k][i],k=to[k][i]; } if (tb==0) return infd; else return (long double) ta/ (long double) tb;}long long ta,tb;void cal(long long k,long long x){ ta=0,tb=0; for (long long i=16;i>=0;--i) { if (to[k][i]&&ta+va[k][i]+tb+vb[k][i]<=x) ta+=va[k][i],tb+=vb[k][i],k=to[k][i]; }}int main(){ scanf("%lld",&n); for (long long i=1;i<=n;++i) scanf("%lld",&h[i]),mp[h[i]]=i; s.insert(inf); s.insert(-inf); init(); scanf("%lld",&x0); for (long long i=1;i<=n;++i) { long double tmp=cal1(i,x0); if (tmp<ans1||(tmp==ans1&&h[i]>h[st1])) ans1=tmp,st1=i; } printf("%lld\n",st1); scanf("%lld",&q); while (q--) { scanf("%lld%d",&st1,&x0); cal(st1,x0); printf("%lld %lld\n",ta,tb); }}
0 0
- 洛谷 P1081 开车旅行
- 洛谷 P1081开车旅行
- 洛谷 P1081 开车旅行(抄)
- 洛谷P1081:开车旅行 (Treap+倍增)
- Luogu P1081 [NOIp2012]开车旅行
- 倍增+双向链表——洛谷P1081 开车旅行
- 【NOIP2012提高组D2T3】【洛谷P1081】开车旅行
- 洛谷 P1081 [NOIP提高组 2012] 开车旅行(线段树+离散化+树上倍增)
- 【NOIP2012】洛谷1081 开车旅行
- 开车旅行
- 开车旅行
- VIJOS 1780 开车旅行
- 【NOIP2012】开车旅行
- NOIP2012 开车旅行 (倍增)
- [noip 2012] 开车旅行
- NOIP2012 开车旅行
- NOIP 2012 开车旅行
- 【noip 2012】开车旅行
- HTML基础01
- Python之自动单元测试之一(unittest使用实例)
- 进程间通信 - 匿名管道实现
- 使用注解配置Spring AOP
- 水经注软件下载的高程数据如何导出DEM格式
- 洛谷 P1081 开车旅行
- easyui-datagrid合并列 C#使用Dynamic泛型计算合并列数据
- php+html5实现文件断点续传
- Shell数组:shell数组的定义、数组长度
- scala获取当前时间戳和今天0时时间戳(精确到秒)的小工具
- 自适应按钮
- Git远程操作详解
- 二叉树的镜像
- Android视频播放框架Vitamio集成及使用MediaPlayer+SurfaceView、VideoView+MediaController实现播放网络视频