题解:
首先我们可以分别建立小 A A 和小 B B 路程森林。其实森林也不用用边表去存储它,只要记录一下 fa[i] f a [ i ] ,即 i i 点的下一个点就可以了
小 A A 和小 B B 旅行就等价于在这些森林里跑,很容易想到树上倍增。
我们可以令 f[i][j] f [ i ] [ j ] 为当前 A A 开车在第 i i 个点经过 2j 2 j 天后到达的点
g1[i][j] g 1 [ i ] [ j ] 为当前 A A 开车在第 i i 个点经过 2j 2 j 天后 A A 走的距离
g2[i][j] g 2 [ i ] [ j ] 为当前 A A 开车在第 i i 个点经过 2j 2 j 天后 B B 走的距离
为什么不需要记录当前 B B 开车的状态?
当 j>=1 j >= 1 时 2j 2 j 后,还是 A A 开车,所以不需要记录 B B 的状态
有了这三个数组,这道题就迎刃而解了。只要结尾状态和一些细节注意一下即可
Code: C o d e :
#include
#define N 100005
#define ll long long
#define inf 0x7fffffff
using namespace std;
struct node
{
int d;ll v;
}p[N];
struct note
{
int mx,mi;
}t[N*5];
bool cmp(node x,node y)
{
return x.v<y.v||x.v==y.v&&x.d<y.d;
}
double sum,ans;
int n,m,tot,x,y,k,h[N],a[N],b[N],w[N],g[N][18];
ll f[N][18][2],ana,anb,v[N];
void change(int v,int l,int r,int x)
{
if(l==r){t[v].mx=t[v].mi=l;return;}
int m=(l+r)/2;
if(x<=m)change(v*2,l,m,x);else
change(v*2+1,m+1,r,x);
t[v].mx=max(t[v*2].mx,t[v*2+1].mx);
t[v].mi=min(t[v*2].mi,t[v*2+1].mi);
}
int getmx(int v,int l,int r,int x,int y)
{
if(x>y)return 0;
if(l==x&&r==y)return t[v].mx;
int m=(l+r)/2;
if(y<=m)return getmx(v*2,l,m,x,y);else
if(x>m)return getmx(v*2+1,m+1,r,x,y);else
return max(getmx(v*2,l,m,x,m),getmx(v*2+1,m+1,r,m+1,y));
}
int getmi(int v,int l,int r,int x,int y)
{
if(x>y)return n+1;
if(l==x&&r==y)return t[v].mi;
int m=(l+r)/2;
if(y<=m)return getmi(v*2,l,m,x,y);else
if(x>m)return getmi(v*2+1,m+1,r,x,y);else
return min(getmi(v*2,l,m,x,m),getmi(v*2+1,m+1,r,m+1,y));
}
void solve(int x,int y)
{
ana=anb=0;
for(int j=17;j>=0;j--)
if(f[x][j][0]+f[x][j][1]<=y)
{
y-=f[x][j][0]+f[x][j][1];
ana+=f[x][j][0];anb+=f[x][j][1];
x=g[x][j];
}
if(f[x][0][0]<=y)ana+=f[x][0][0];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&v[i]),p[i].v=v[i],p[i].d=i;
sort(p+1,p+n+1,cmp);
v[0]=inf;
for(int i=1;i<=n;i++)
h[p[i].d]=++tot,w[tot]=p[i].d;
for(int i=1;i<=n*5;i++)t[i].mi=n+1;
for(int i=n;i>=1;i--)
{
p[1].d=getmi(1,1,n,h[i]+1,n);p[2].d=getmx(1,1,n,1,h[i]-1);
p[3].d=getmi(1,1,n,p[1].d+1,n);p[4].d=getmx(1,1,n,1,p[2].d-1);
for(int j=1;j<=4;j++)p[j].v=abs(v[i]-v[w[p[j].d]]);
sort(p+1,p+5,cmp);
if(p[1].d!=0&&p[1].d!=n+1)b[i]=w[p[1].d];
if(p[2].d!=0&&p[2].d!=n+1)a[i]=w[p[2].d];
change(1,1,n,h[i]);
}
for(int i=1;i<=n;i++)
{
g[i][0]=b[a[i]];
f[i][0][0]=abs(v[i]-v[a[i]]);
f[i][0][1]=abs(v[a[i]]-v[b[a[i]]]);
}
for(int j=1;j<=17;j++)
for(int i=1;i<=n;i++)
{
g[i][j]=g[g[i][j-1]][j-1];
f[i][j][0]=f[i][j-1][0]+f[g[i][j-1]][j-1][0];
f[i][j][1]=f[i][j-1][1]+f[g[i][j-1]][j-1][1];
}
scanf("%d",&x);ans=inf;
for(int i=1;i<=n;i++)
{
solve(i,x);
if(!anb)sum=inf;
else sum=ana*1.0/anb;
if(sumv[k])
ans=sum,k=i;
}
printf("%d\n",k);
for(scanf("%d",&m);m;m--)
{
scanf("%d%d",&x,&y);
solve(x,y);
printf("%lld %lld\n",ana,anb);
}
}