以后序列上的问题可以想一想倍增。。
s
a
[
i
]
/
s
b
[
i
]
sa[i]/sb[i]
sa[i]/sb[i]记录在
i
i
i这个位置让
A
/
B
A/B
A/B开车到达的点。
把
A
A
A和
B
B
B都跳一次称为一轮。
d
i
s
[
i
]
[
j
]
dis[i][j]
dis[i][j]表示从
i
i
i跳
2
j
2^j
2j轮的总路程。
p
o
s
[
i
]
[
j
]
pos[i][j]
pos[i][j]表示从
i
i
i跳
2
j
2^j
2j轮后的位置。
d
i
s
_
a
[
i
]
[
j
]
dis\_a[i][j]
dis_a[i][j]表示从
i
i
i跳
2
j
2^j
2j轮
A
A
A所走的总路程。
B
B
B的路程用总路程减去
A
A
A的路程即可。
最近点和次近点用 s e t set set查一查,要注意距离相同时按照海拔从小到大排。
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
#define pii std::pair<int,int>
#define mp std::make_pair
#define se second
#define fi first
cs int N=1e5+10,oo=1e9+7,Log=17;
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
template <typename T>
inline T get(){
char ch=gc();T x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=0;ch=gc();}
while(isdigit(ch)) x=((x+(x<<2))<<1)+(ch^48),ch=gc();
return f?x:-x;
}
inline int gi(){return get<int>();}
inline ll gl(){return get<ll>();}
}
using IO::gi;
using IO::gl;
inline int min(int x,int y){return x<y?x:y;}
inline void Min(int &x,int y){if(x>y)x=y;}
int n,m,sa[N],sb[N],pos[N][Log],ans1=1;
pii h[N];ll dis_a[N][Log],dis_b[N],dis[N][Log],x_0;
double quo;ll suma,sumb;
std::set<pii> S;
std::set<pii>::iterator It;
inline int pre(cs pii &H){
It=S.lower_bound(H);
return It==S.begin()?0:(*(--It)).se;
}
inline int suf(cs pii &H){
It=S.upper_bound(H);
return It==S.end()?0:(*It).se;
}
std::vector<pii> x;
inline bool cmp(cs pii &a,cs pii &b){
return a.fi==b.fi?h[a.se].fi<h[b.se].fi:a.fi<b.fi;
}
int main(){
// freopen("1817.in","r",stdin);
n=gi();
for(int re i=1;i<=n;++i) h[i].fi=gi(),h[i].se=i;
for(int re i=n,pos1,pos2,sz;i>=1;--i){
S.insert(h[i]),sa[i]=sb[i]=0,x.clear();
pos1=pre(h[i]),pos2=suf(h[i]);
if(pos1) x.push_back(mp(h[i].fi-h[pos1].fi,pos1)),pos1=pre(h[pos1]);
if(pos2) x.push_back(mp(h[pos2].fi-h[i].fi,pos2)),pos2=suf(h[pos2]);
if(pos1) x.push_back(mp(h[i].fi-h[pos1].fi,pos1));
if(pos2) x.push_back(mp(h[pos2].fi-h[i].fi,pos2));
sz=x.size(),sort(x.begin(),x.end(),cmp);
if(sz>=1) sb[i]=x[0].se;if(sz>=2) sa[i]=x[1].se;
if(sa[i]) dis_a[i][0]=x[1].fi;if(sb[i]) dis_b[i]=x[0].fi;
if(pos[i][0]=sb[sa[i]]) dis[i][0]=dis_a[i][0]+dis_b[sa[i]];
}
for(int re j=1;(1<<j)<=n;++j)
for(int re i=1;i<=n;++i) if(pos[pos[i][j-1]][j-1])
pos[i][j]=pos[pos[i][j-1]][j-1],
dis[i][j]=dis[pos[i][j-1]][j-1]+dis[i][j-1],
dis_a[i][j]=dis_a[pos[i][j-1]][j-1]+dis_a[i][j-1];
x_0=gl(),quo=oo;
for(int re i=1,now;i<=n;++i){
ll X=x_0;suma=sumb=0,now=i;double sum=oo;
for(int re j=Log-1;~j;--j) if(pos[now][j]&&dis[now][j]<=X)
X-=dis[now][j],suma+=dis_a[now][j],sumb+=dis[now][j]-dis_a[now][j],now=pos[now][j];
if(sa[now]&&dis_a[now][0]<=X) suma+=dis_a[now][0];
if(sumb) sum=1.0*suma/sumb;
if((sum<quo)||(sum==quo&&h[i].fi>h[ans1].fi)) quo=sum,ans1=i;
}printf("%d\n",ans1);
m=gi();
for(int re i=1;i<=m;++i){
int now=gi();ll go=gl();suma=sumb=0;
for(int re j=Log-1;~j;--j) if(pos[now][j]&&dis[now][j]<=go)
go-=dis[now][j],suma+=dis_a[now][j],sumb+=dis[now][j]-dis_a[now][j],now=pos[now][j];
if(sa[now]&&dis_a[now][0]<=go) suma+=dis_a[now][0];
printf("%lld %lld\n",suma,sumb);
}
}