因为要快速查找向后跳应该是哪一个点,所以用set,迭代器左右晃一下查找最接近的两个元素(P选手是不是只能用平衡树~)。然后用倍增记录i节点跳2^j步后,A和B分别走的距离。具体的细节和统计答案也需要注意。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<algorithm>
#define maxn 100005
#define LL long long
using namespace std;
set<LL> Set;
set<LL>::iterator it,pre,nxt;
map<LL,int> id;
int fa[maxn][20];
int tt[maxn];
LL dis[maxn][20][2];
LL dp[maxn][2];
void read(LL &a)
{
a=0;LL f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
a*=10;a+=c-'0';
c=getchar();
}a*=f;
}
LL H[maxn];
int n,cnt;
LL inf=1e10;
struct str{
int id;LL key,num;
}sor[6];
bool cid(str A,str B)
{
if(A.key!=B.key)
return A.key<B.key;
return A.num<B.num;
}
void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
read(H[i]);
Set.insert(H[i]);
id[H[i]]=i;
}
for(int i=1;i<n;i++)
{
nxt=pre=it=Set.find(H[i]);
cnt=0;
nxt++;
if(nxt!=Set.end())
{
LL N1=*nxt;int n1=id[N1];
sor[++cnt].key=abs(N1-H[i]),sor[cnt].id=n1,sor[cnt].num=N1;
nxt++;
if(nxt!=Set.end())
{
LL N2=*nxt;int n2=id[N2];
sor[++cnt].key=abs(N2-H[i]),sor[cnt].id=n2,sor[cnt].num=N2;
}
}
if(it!=Set.begin())
{
pre--;LL P1=*pre;int p1=id[P1];
sor[++cnt].key=abs(P1-H[i]),sor[cnt].id=p1,sor[cnt].num=P1;
if(pre!=Set.begin())
{
pre--;LL P2=*pre;int p2=id[P2];
sor[++cnt].key=abs(P2-H[i]),sor[cnt].id=p2,sor[cnt].num=P2;
}
}
sort(sor+1,sor+cnt+1,cid);
int j=sor[1].id;
if(cnt>0)
{
tt[i]=j;
dis[i][0][1]=(LL)sor[1].key;
}
j=sor[2].id;
if(cnt>1)
{
fa[i][0]=j;
dis[i][0][0]=(LL)sor[2].key;
}
Set.erase(H[i]);
id[H[i]]=0;
}
for(int j=1;j<=18;j++)
for(int i=1;i<n;i++)
{
if(j==1)
{
fa[i][j]=tt[fa[i][0]];
dis[i][j][0]=dis[i][0][0];
dis[i][j][1]=dis[fa[i][0]][0][1];
}
else
{
fa[i][j]=fa[fa[i][j-1]][j-1];
if(fa[i][j])
{
dis[i][j][0]=dis[i][j-1][0]+dis[fa[i][j-1]][j-1][0];
dis[i][j][1]=dis[i][j-1][1]+dis[fa[i][j-1]][j-1][1];
}
}
}
}
struct Ans{
LL da,db;
};
Ans calc(int i,LL x)
{
Ans r;
LL d=0,da=0,db=0;int u=i;
for(int j=18;j>=1;j--)
{
if(dis[u][j][1]||dis[u][j][0])
if(dis[u][j][1]+dis[u][j][0]+d<=x)
{
da+=dis[u][j][0];
db+=dis[u][j][1];
d=da+db;
u=fa[u][j];
}
}
if(dis[u][0][0]+d<=x) da+=dis[u][0][0];
r.da=da;r.db=db;
return r;
}
int main()
{
init();
LL fz=inf,fm=0,x,da,db;
int pos=0;cin>>x;
for(int i=1;i<=n;i++)
{
Ans r=calc(i,x);
da=r.da;db=r.db;
if(da*fm<fz*db&&da!=0)
{fz=da;fm=db;pos=i;}
else if(da!=0&&da*fm==fz*db&&H[pos]<H[i])
{fz=da;fm=db;pos=i;}
if(da==0&&fm==0&&H[pos]<H[i])
{fz=da;fm=db;pos=i;}
}
cout<<pos<<endl;
int m;scanf("%d",&m);
for(int i=1;i<=m;i++)
{
int s;scanf("%d",&s);
LL x;read(x);
Ans r=calc(s,x);
printf("%lld %lld\n",r.da,r.db);
}
return 0;
}