Description
小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想知道两个问题:
- 对于一个给定的X=X0,从哪一个城市出发,小A开车行驶的路程总数与小B行驶的路程总数的比值最小(如果小B的行驶路程为0,此时的比值可视为无穷大,且两个无穷大视为相等)。如果从多个城市出发,小A开车行驶的路程总数与小B行驶的路程总数的比值都最小,则输出海拔最高的那个城市。
- 对任意给定的X=Xi 和出发城市Si,小A开车行驶的路程总数以及小B行驶的路程总数。
Input Format
第一行包含一个整数N,表示城市的数目。
第二行有N个整数,每两个整数之间用一个空格隔开,依次表示城市1到城市N的海拔高度,即H1,H2,……,Hn,且每个Hi 都是不同的。
第三行包含一个整数X0。
第四行为一个整数M,表示给定M组Si和Xi。
接下来的M行,每行包含2个整数Si 和Xi,表示从城市Si 出发,最多行驶Xi 公里。
Output Format
输出共M+1行。
第一行包含一个整数S0,表示对于给定的X0,从编号为S0的城市出发,小A开车行驶 的路程总数与小B行驶的路程总数的比值最小。
接下来的M行,每行包含2个整数,之间用一个空格隔开,依次表示在给定的Si 和Xi 下小A行驶的里程总数和小B行驶的里程总数。
Sample Input
样例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
Sample Output
样例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
Hint
对于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 互不相同。
【题解】
倍增 双向链表
首先一定要预处理在A和B在每个点上出发到达的点(可以用各种数据结构处理),推荐比较高效的双向链表(与noip2016初赛完善程序第一题一样)
然后用倍增的做法f[i][j]记录从i点出发AB轮换2^j轮后到达的地点(一轮是AB都开了一次车)
g[i][j][0]i到f[i][j]中A走的路程 g[i][j][1]记录B的路程
对于第一问枚举每一个起点倍增到不能走 最后比较一下就行了
第二问就直接从给定起点做倍增就行
详见代码
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
long long g[100005][22][2],a,b,l,x;
double MIN,d;
int f[100005][22],get[100005][2],rank[100005],lef[100005],rig[100005];
struct info
{
long long h;
int num;
}city[100005],t[10];
int i,j,k,m,n,ans,s;
bool cmp(info x,info y) {return x.h<y.h;}
bool cmp1(info x,info y) {return (x.h<y.h || (x.h==y.h&&city[rank[x.num]].h<city[rank[y.num]].h));}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%lld",&city[i].h),city[i].num=i;
sort(city+1,city+n+1,cmp);
for (i=1;i<=n;i++) rank[city[i].num]=i;
for (i=1;i<=n;i++) lef[i]=i-1,rig[i]=i+1;
city[0].h=city[n+1].h=1e9;
for (i=1;i<=n;i++)
{
k=0;
if (lef[rank[i]]!=0) t[++k]={abs(city[lef[rank[i]]].h-city[rank[i]].h),city[lef[rank[i]]].num};
if (rig[rank[i]]!=n+1) t[++k]={abs(city[rig[rank[i]]].h-city[rank[i]].h),city[rig[rank[i]]].num};
if (lef[lef[rank[i]]]!=0) t[++k]={abs(city[lef[lef[rank[i]]]].h-city[rank[i]].h),city[lef[lef[rank[i]]]].num};
if (rig[rig[rank[i]]]!=n+1) t[++k]={abs(city[rig[rig[rank[i]]]].h-city[rank[i]].h),city[rig[rig[rank[i]]]].num};
sort(t+1,t+k+1,cmp1);
rig[lef[rank[i]]]=rig[rank[i]];
lef[rig[rank[i]]]=lef[rank[i]];
if (k>0) get[i][1]=t[1].num;
if (k>1) get[i][0]=t[2].num;
}
for (i=1;i<=n;i++)
{
j=get[i][0];k=get[j][1];
if (k!=0) f[i][0]=k;else f[i][0]=i;
if (j!=0) g[i][0][0]=abs(city[rank[i]].h-city[rank[j]].h);else g[i][0][0]=1e15;
if (j!=0&&k!=0) g[i][0][1]=abs(city[rank[j]].h-city[rank[k]].h);else g[i][0][1]=1e15;
}
for (i=1;i<=20;i++)
for (j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
if (g[j][i-1][0]==1e15||g[f[j][i-1]][i-1][0]==1e15) g[j][i][0]=1e15;
else g[j][i][0]=g[j][i-1][0]+g[f[j][i-1]][i-1][0];
if (g[j][i-1][1]==1e15||g[f[j][i-1]][i-1][1]==1e15) g[j][i][1]=1e15;
else g[j][i][1]=g[j][i-1][1]+g[f[j][i-1]][i-1][1];
}
scanf("%d",&x);MIN=1e16;
for (i=1;i<=n;i++)
{
l=0;k=i;a=0;b=0;
for (;l+g[k][0][0]+g[k][0][1]<=x;)
{
for (j=0;l+g[k][j][0]+g[k][j][1]<=x;j++);j--;
l+=g[k][j][0]+g[k][j][1];
a+=g[k][j][0];b+=g[k][j][1];
k=f[k][j];
}
if (l+g[k][0][0]<=x) a+=g[k][0][0];
if (b==0) d=1e15;else d=a/1.0/b;
if (d<MIN) ans=i,MIN=d;
}
printf("%d\n",ans);
for (scanf("%d",&m);m;m--)
{
scanf("%d%lld",&s,&x);
l=0;k=s;a=0;b=0;
for (;l+g[k][0][0]+g[k][0][1]<=x;)
{
for (j=0;l+g[k][j][0]+g[k][j][1]<=x;j++);j--;
l+=g[k][j][0]+g[k][j][1];
a+=g[k][j][0];b+=g[k][j][1];
k=f[k][j];
}
if (l+g[k][0][0]<=x) a+=g[k][0][0];
printf("%lld %lld\n",a,b);
}
}