开车旅行(codevs 1199)
小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行驶的路程总数的比值都最小,则输出海拔最高的那个城市。
2.对任意给定的 X=Xi和出发城市 Si,小 A 开车行驶的路程总数以及小 B 行驶的路程总数。

第一行包含一个整数 N,表示城市的数目。
第二行有 N 个整数,每两个整数之间用一个空格隔开,依次表示城市 1 到城市 N 的海拔高度,即H1,H2,……,Hn,且每个Hi都是不同的。
第三行包含一个整数 X0。
第四行为一个整数 M,表示给定M组Si和 Xi。
接下来的M行,每行包含2个整数Si和Xi,表示从城市 Si出发,最多行驶Xi公里。
输出共M+1 行。
第一行包含一个整数S0,表示对于给定的X0,从编号为S0的城市出发,小A开车行驶的路程总数与小B行驶的路程总数的比值最小。
接下来的 M 行,每行包含 2 个整数,之间用一个空格隔开,依次表示在给定的 Si和Xi下小A行驶的里程总数和小B 行驶的里程总数。
【样例1】
4
2 3 1 4
3
4
1 3
2 3
3 3
4 3
【样例2】
10
4 5 6 1 2 3 7 8 9 10
7
10
1 7
2 7
3 7
4 7
5 7
6 7
7 7
8 7
9 7
10 7
【样例1】
1
1 1
2 0
0 0
0 0
【样例2】
2
3 2
2 4
2 1
2 4
5 1
5 1
2 1
2 0
0 0
0 0
【输入输出样例1说明】
各个城市的海拔高度以及两个城市间的距离如上图所示。
如果从城市1出发, 可以到达的城市为2,3,4,这几个城市与城市 1的距离分别为 1,1,2,但是由于城市3的海拔高度低于城市 2,所以我们认为城市 3离城市 1最近,城市 2离城市1 第二近,所以小 A 会走到城市 2。到达城市 2 后,前面可以到达的城市为 3,4,这两个城市与城市 2 的距离分别为 2,1,所以城市 4离城市 2最近,因此小 B 会走到城市 4。到达城市4后,前面已没有可到达的城市,所以旅行结束。
如果从城市2出发,可以到达的城市为3,4,这两个城市与城市 2 的距离分别为 2,1,由于城市3离城市2第二近,所以小A会走到城市 3。到达城市3后,前面尚未旅行的城市为4,所以城市 4 离城市 3 最近,但是如果要到达城市 4,则总路程为 2+3=5>3,所以小 B 会直接在城市3结束旅行。
如果从城市3出发,可以到达的城市为4,由于没有离城市3 第二近的城市,因此旅行还未开始就结束了。
如果从城市4出发,没有可以到达的城市,因此旅行还未开始就结束了。
【输入输出样例2说明】
当 X=7时,
如果从城市1出发,则路线为 1 -> 2 -> 3 -> 8 -> 9,小A 走的距离为1+2=3,小B走的距离为 1+1=2。(在城市 1 时,距离小 A 最近的城市是 2 和 6,但是城市 2 的海拔更高,视为与城市1第二近的城市,所以小A 最终选择城市 2;走到9后,小A只有城市10 可以走,没有第2选择可以选,所以没法做出选择,结束旅行)
如果从城市2出发,则路线为 2 -> 6 -> 7 ,小A 和小B走的距离分别为 2,4。
如果从城市3出发,则路线为 3 -> 8 -> 9,小A和小B走的距离分别为 2,1。
如果从城市4出发,则路线为 4 -> 6 -> 7,小A和小B走的距离分别为 2,4。
如果从城市5出发,则路线为 5 -> 7 -> 8 ,小A 和小B走的距离分别为 5,1。
如果从城市6出发,则路线为 6 -> 8 -> 9,小A和小B走的距离分别为 5,1。
如果从城市7出发,则路线为 7 -> 9 -> 10,小A 和小B走的距离分别为 2,1。
如果从城市8出发,则路线为 8 -> 10,小A 和小B走的距离分别为2,0。
如果从城市 9 出发,则路线为 9,小 A 和小 B 走的距离分别为 0,0(旅行一开始就结束了)。
如果从城市10出发,则路线为 10,小A 和小B 走的距离分别为0,0。
从城市 2 或者城市 4 出发小 A 行驶的路程总数与小 B 行驶的路程总数的比值都最小,但是城市2的海拔更高,所以输出第一行为2。
【数据范围】
对于30%的数据,有1≤N≤20,1≤M≤20;
对于40%的数据,有1≤N≤100,1≤M≤100;
对于50%的数据,有1≤N≤100,1≤M≤1,000;
对于70%的数据,有1≤N≤1,000,1≤M≤10,000;
对于100%的数据,有1≤N≤100,000, 1≤M≤10,000, -1,000,000,000≤Hi≤1,000,000,000,0≤X0≤1,000,000,000,1≤Si≤N,0≤Xi≤1,000,000,000,数据保证Hi互不相同。
/*
第一遍打暴力就得了25分,原因是求第一问时写 double(pa/pb) 是不对的,
应该写 double(pa)/double(pb),改完得了70分
正解:暴力的预处理是n^2的,改成用set预处理时(o)n的,并且查询时
用倍增查询
*/
#include<cstdio>
#include<iostream>
#include<map>
#include<cstdlib>
#include<algorithm>
#include<set>
#define M 100010
#define ll long long
#define inf 500000000000LL
using namespace std;
int n,h[M],fa[M],fb[M],to[M][];
ll a[M],b[M],va[M][],vb[M][];
map<ll,int> mp;
set<ll> q;
struct node{ll key,h;}t[];
bool operator<(node a,node b)
{
return (a.key<b.key||(a.key==b.key&&a.h<b.h));
}
int read()
{
char c=getchar();int num=,flag=;
while(c<''||c>''){if(c=='-')flag=-;c=getchar();}
while(c>=''&&c<=''){num=num*+c-'';c=getchar();}
return num*flag;
}
void build()
{
for(int i=n;i;i--)
{
q.insert(h[i]);
t[].h=*--q.lower_bound(h[i]);t[].h=*q.upper_bound(h[i]);
if(t[].h!=-inf) t[].h=*--q.lower_bound(t[].h);
else t[].h=-inf;
if(t[].h!=inf) t[].h=*q.upper_bound(t[].h);
else t[].h=inf;
for(int j=;j<=;j++)
t[j].key=abs(h[i]-t[j].h);
sort(t+,t+);
a[i]=t[].key;fa[i]=mp[t[].h];
b[i]=t[].key;fb[i]=mp[t[].h];
for(int j=;j<=;j++)
if(!j)
{
if(fa[i])va[i][]=a[i],to[i][]=fa[i];
}
else if(j==)
{
if(fb[fa[i]])va[i][]=a[i],vb[i][]=b[fa[i]],to[i][]=fb[fa[i]];
}
else if(to[to[i][j-]][j-])
{
to[i][j]=to[to[i][j-]][j-];
va[i][j]=va[i][j-]+va[to[i][j-]][j-];
vb[i][j]=vb[i][j-]+vb[to[i][j-]][j-];
}
else break;
}
}
void solve1()
{
int x0=read(),ans=;double mn=1e60;
for(int i=;i<=n;i++)
{
int pa=,pb=,s=i;
for(int j=;j>=;j--)
if(to[s][j]&&pa+pb+va[s][j]+vb[s][j]<=x0)
{
pa+=va[s][j];pb+=vb[s][j];
s=to[s][j];
}
if(pb)
if(mn>(double)pa/(double)pb||(mn==(double)pa/(double)pb&&h[i]>h[ans]))
{
mn=(double)pa/(double)pb;ans=i;
}
}
printf("%d\n",ans);
}
void solve2()
{
int m=read();
while(m--)
{
int s=read(),x=read(),pa=,pb=;
for(int i=;i>=;i--)
if(to[s][i]&&pa+pb+va[s][i]+vb[s][i]<=x)
{
pa+=va[s][i];pb+=vb[s][i];
s=to[s][i];
}
printf("%d %d\n",pa,pb);
}
}
int main()
{
freopen("jh.in","r",stdin);
n=read();
for(int i=;i<=n;i++)
h[i]=read(),mp[h[i]]=i;
q.insert(-inf);q.insert(inf);
build();
solve1();
solve2();
return ;
}
开车旅行(codevs 1199)的更多相关文章
- vijos P1780 【NOIP2012】 开车旅行
描述 小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为 ...
- 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.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...
随机推荐
- 08 H5新增input元素
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- python_数据类型基本操作(2)
概览: 第1章 基础数据类型宏观的初识第2章 int 第3章 bool 第4章 str 4.1 python体现形式 4.2 引号用法 4.3 字符串运算 4.3.1 字符串相加 4.3.2 字符串相 ...
- [BZOJ4815][CQOI2017]小Q的表格 数论+分块
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4815 题目中所给条件中的$(a,a+b)$和$(a,b)$的关系很瞩目. 然后大家都知道$ ...
- GCC的函数声明问题
Thinking in C++ 第四章 GCC 不需要再MAIN函数前声明 编译也能通过. G++不行.
- 关于react native在window下运行安卓的时候报 could not connect to development server
当出现这种问题是网上的解答方案都是一模一样的! 我这边先给个地址讲的是解决方案http://blog.csdn.net/qq_25827845/article/details/52974991 但是我 ...
- 解决hibernate对Sql Server分页慢的问题
一.hibernate分页 hibernate对MsSql的伪分页 分页是web项目中比不可少的一个功能,数据量大的时候不能全部展示必然要用到分页技术.相信大家对hibernate中的分页都不陌生: ...
- git 出现 The current branch is not configured for pull No value for key branch.master.merge found in configuration
以下是我在网上找到的不错的文章,我参考后已解决我的问题: http://my.oschina.net/robinsonlu/blog/144085 http://www.cnblogs.com/zha ...
- velocity(vm)模板引擎基本语法
for循环 #foreach($acc in $!{param.tools}) #set($count = $count + 1) <li custom-data="$!{acc.or ...
- vue中去掉烦人的格式警告(eslint )
解决办法: 一,源头上解决,下次创建项目时就不要使用eslint连接项目代码 如上图所示,就是在这一步的时候选择no: 二,在build文件夹中找到webpack.base.conf.js文件 找到右 ...
- IDEA修改背景图片和主题代码风格
使用IDEA有一段时间了,之前为了写代码没时间折腾这玩意,以前使用Eclipse的时候一次性折腾好了,现在把之前Eclipse的配置再配到IDEA里面来,下面是效果图.Eclipse的设置见:点击这里 ...