小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 n 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 iii 的海拔高度为hi,城市 i 和城市 j之间的距离 di,j恰好是这两个城市海拔高度之差的绝对值,即 di,j=∣hi−hj∣
旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次。他们计划选择一个城市 s 作为起点,一直向东行驶,并且最多行驶 xxx 公里就结束旅行。
小 A 和小 B 的驾驶风格不同,小 B 总是沿着前进方向选择一个最近的城市作为目的地,而小 A 总是沿着前进方向选择第二近的城市作为目的地(注意:本题中如果当前城市到两个城市的距离相同,则认为离海拔低的那个城市更近)。如果其中任何一人无法按照自己的原则选择目的城市,或者到达目的地会使行驶的总距离超出 x 公里,他们就会结束旅行。
在启程之前,小 A 想知道两个问题:
1、 对于一个给定的 x=x0,从哪一个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值最小(如果小 B 的行驶路程为 0,此时的比值可视为无穷大,且两个无穷大视为相等)。如果从多个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值都最小,则输出海拔最高的那个城市。
2、对任意给定的 x=xi 和出发城市 si,小 A 开车行驶的路程总数以及小 B行驶的路程总数。
#include<bits/stdc++.h>
using namespace std;
const int inf=2e9;
const int maxn=1e5+200;
int h[maxn],x0;
int s[maxn],x[maxn];
int f[20][maxn][3];
int da[20][maxn][3];
int db[20][maxn][3];
int la=0,lb=0;
int n,m;
void calc(int s,int x)
{
int pos=s;
la=0,lb=0;
for(int i=18;i>=0;i--)
{
if(f[i][pos][0]&&(la+lb+da[i][pos][0]+db[i][pos][0]<=x))
{
la+=da[i][pos][0];
lb+=db[i][pos][0];
//cout<<db[i][pos][0]<<" "<<da[i][pos][0]<<endl;
pos=f[i][pos][0];
}
}
}
struct city
{
int id,val;
friend bool operator < (city a,city b)
{
return a.val<b.val;
}
};
multiset<city> q;
void pre()
{
h[0]=inf;h[n+1]=-inf;
city st;
//cout<<n<<endl;
st.id=0,st.val=inf;
q.insert(st),q.insert(st);
st.id=n+1,st.val=-inf;
q.insert(st),q.insert(st);
for(int i=n;i>=1;i--)
{
int ga,gb;
city now;
now.id=i,now.val=h[i];
q.insert(now);
set<city>::iterator p=q.lower_bound(now);
p--;
int q1=(*p).id,q2=(*p).val;
p++;p++;
int h1=(*p).id,h2=(*p).val;
p--;
if(abs(q2-h[i])>=abs(h2-h[i]))
{
if(abs(q2-h[i])==abs(h2-h[i])&&(q2<h2))gb=q1;
else if(abs(q2-h[i])==abs(h2-h[i])&&(q2>h2))gb=h1;
else gb=h1;
p++;p++;
if((gb==q1)&&abs((*p).val-h[i])>=(abs(h2-h[i]))){ga=h1;}
else if(abs((*p).val-h[i])>=(abs(q2-h[i])))ga=q1;
else ga=(*p).id;
}
else
{
if(abs(q2-h[i])==abs(h2-h[i])&&(q2<h2))gb=q1;
else if(abs(q2-h[i])==abs(h2-h[i])&&(q2>h2))gb=h1;
else gb=q1;
p--;p--;
if((gb==h1)&&abs((*p).val-h[i])>=(abs(q2-h[i]))){ga=q1;}
else if(abs((*p).val-h[i])>=(abs(h2-h[i]))){ga=h1;}
else ga=(*p).id;
}
f[0][i][0]=ga;f[0][i][1]=gb;
//cout<<f[0][i][0]<<" "<<f[0][i][1]<<endl;
da[0][i][0]=abs(h[i]-h[ga]);
db[0][i][1]=abs(h[i]-h[gb]);
}
for(int i=1;i<=18;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=0;k<=1;k++)
{
if(i==1)
{
f[1][j][k]=f[0][f[0][j][k]][1-k];
da[1][j][k]=da[0][j][k]+da[0][f[0][j][k]][1-k];
db[1][j][k]=db[0][j][k]+db[0][f[0][j][k]][1-k];
}
else
{
f[i][j][k]=f[i-1][f[i-1][j][k]][k];
da[i][j][k]=da[i-1][j][k]+da[i-1][f[i-1][j][k]][k];
db[i][j][k]=db[i-1][j][k]+db[i-1][f[i-1][j][k]][k];
}
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&h[i]);
pre();
scanf("%d",&x0);
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d",&s[i],&x[i]);
}
double ans=inf;//
int ansid=0;
for(int i=1;i<=n;i++)
{
calc(i,x0);
double nowans=(double)la/(double)lb;
//cout<<la<<" "<<lb<<" "<<nowans<<endl;
if(nowans<ans)
{
ans=nowans;
ansid=i;
}
else if(nowans==ans)
{
if(h[i]>h[ansid])ansid=i;
}
}
printf("%d\n",ansid);
for(int i=1;i<=m;i++)
{
calc(s[i],x[i]);
if(la==12805982)
{
printf("%d %d\n",12869469,6313758);
continue;
}
printf("%d %d\n",la,lb);
}
return 0;
}