题目见[NOIP2012 提高组] 开车旅行 - 洛谷(懒得打题目了。。。)
我们直接上代码
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#include<stack>
#define lst long long
#define rg register
#define N 100050
#define Inf 2147483647
using namespace std;
int n,m,X0,ans=n;
struct CITY{
lst v;
int num,l,r;
}ljl[N];
int back[N],go[N],nA[N],nB[N];
int f[N][20];
lst disA[N][20],disB[N][20],a,b;
double minn=2147483647;
inline lst read()
{
rg lst s=0,m=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')m=-1,ch=getchar();
while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
return s*m;
}
inline int cmp(rg const CITY &a,rg const CITY &b){return a.v<b.v;}
inline int dis(rg int p,rg int q){return abs(ljl[p].v-ljl[q].v);}
inline int pd(rg int x,rg int y,rg int now)
{
if(!x)return 0;
if(!y)return 1;
return dis(x,now)<=dis(y,now);//返回小一些的
}
inline void solve(rg int tt,rg int now)
{
rg int ll=ljl[now].l,rr=ljl[now].r;
if(pd(ll,rr,now))
if(pd(ljl[ll].l,rr,now))
nB[tt]=back[ll],nA[tt]=back[ljl[ll].l];
else
nB[tt]=back[ll],nA[tt]=back[rr];
else
if(pd(ll,ljl[rr].r,now))
nB[tt]=back[rr],nA[tt]=back[ll];
else
nB[tt]=back[rr],nA[tt]=back[ljl[rr].r];
if(ll)ljl[ll].r=rr;
if(rr)ljl[rr].l=ll;
}
inline void Prepare()
{
n=read();
for(rg int i=1;i<=n;++i)ljl[i].v=read(),ljl[i].num=i;
sort(ljl+1,ljl+n+1,cmp);
for(rg int i=1;i<=n;++i)back[i]=ljl[i].num,go[back[i]]=i;
for(rg int i=1;i<=n;++i)ljl[i].l=i-1,ljl[i].r=i+1;
ljl[1].l=ljl[n].r=0;
for(rg int i=1;i<=n;++i)solve(i,go[i]);
}
inline void Bz()
{
for(rg int i=1;i<=n;++i)
{
f[i][0]=nB[nA[i]];
disA[i][0]=dis(go[i],go[nA[i]]);
disB[i][0]=dis(go[nA[i]],go[f[i][0]]);
}
for(rg int j=1;j<=19;++j)
for(rg int i=1;i<=n;++i)
{
f[i][j]=f[f[i][j-1]][j-1];
disA[i][j]=disA[i][j-1]+disA[f[i][j-1]][j-1];
disB[i][j]=disB[i][j-1]+disB[f[i][j-1]][j-1];
}
/* for(rg int i=1;i<=n;++i)
for(rg int j=0;j<=3;++j)
{
printf(" f[%d][%d]=%d\n",i,j,f[i][j]);
printf("disA[%d][%d]=%lld\n",i,j,disA[i][j]);
printf("disB[%d][%d]=%lld\n",i,j,disB[i][j]);
}
*/}
inline void getab(rg int x,rg int now)
{
a=b=0;
for(rg int i=19;i>=0;--i)
if(f[now][i]&&(a+b+disA[now][i]+disB[now][i]<=x))
a+=disA[now][i],b+=disB[now][i],now=f[now][i];
if(nA[now]&&a+b+disA[now][0]<=x)a+=disA[now][0];
}
int main()
{
Prepare();
Bz();
X0=read(),m=read();
for(rg int i=1;i<=n;++i)
{
getab(X0,i);
if(b&&1.0*a/b<minn)
minn=1.0*a/b,ans=i;
}
printf("%d\n",ans);
for(rg int i=1;i<=m;++i)
{
rg int s=read(),x=read();
getab(x,s);
printf("%lld %lld\n",a,b);
}
return 0;
}