在倍增LCA的基础上做一些改进。
开四个二位数组ma,mi,premax,submax分别表示:从i到anc[i][...]的最大,最小值,从i到anc[i][...]的最大获利,从anc[i][...]到i的最大获利。
考虑如何更新?对于ma,mi,直接依照anc的方法进行更新即可。
对于premax,submax,则要再考虑行走方向,依据ma,mi进行更新。转移方程见方程。
考虑如何倍增求值?
令x,y的lca为z。分成从x到z,从y到z两步处理。
每次考虑运用ma配mi,premax或submax对ans进行更新,并记录maxx或minn值。
两步进行完之后,再maxx-minn与ans最后更新,即可得到正解。
注意?数组大小!!!!!!!!附上程序。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define maxv 400050
#define maxe 400050
#define maxq 10050
using namespace std;
struct edge
{
long long v,nxt;
}e[maxe];
long long g[maxv]={0},n,m,x,y,price[maxv],nume=0;
long long ma[maxv][22]={0},mi[maxv][22],premax[maxv][22]={0},submax[maxv][22]={0},anc[maxv][22]={0};
long long dis[maxv]={0},ans=0;
bool vis[maxv]={false};
void addedge(long long u,long long v)
{
e[++nume].v=v;
e[nume].nxt=g[u];
g[u]=nume;
}
void dfs(long long u)
{
vis[u]=true;
for (long long i=g[u];i;i=e[i].nxt)
{
long long v=e[i].v;
if (vis[v]==false)
{
anc[v][0]=u;
ma[v][0]=max(price[v],price[u]);
mi[v][0]=min(price[v],price[u]);
premax[v][0]=price[u]-price[v];
submax[v][0]=price[v]-price[u];
dis[v]=dis[u]+1;
dfs(v);
}
}
}
long long lca(long long x,long long y)
{
if (dis[x]>dis[y]) swap(x,y);
for (long long i=14;i>=0;i--)
{
if (dis[anc[y][i]]>=dis[x])
y=anc[y][i];
}
for (long long i=14;i>=0;i--)
{
if (anc[x][i]!=anc[y][i])
{
x=anc[x][i];
y=anc[y][i];
}
}
if (x==y) return x;
else return anc[x][0];
}
void jump()
{
ans=0;
long long z=lca(x,y),minn=1234567,maxx=0;
long long t;
t=dis[x]-dis[z];
if (t>0)
{
for (long long i=14;i>=0;i--)
{
if (t>=(1<<i))//
{
t=t-(1<<i);
ans=max(premax[x][i],ans);
ans=max(ma[x][i]-minn,ans);
minn=min(minn,mi[x][i]);
x=anc[x][i];
}
}
}
t=dis[y]-dis[z];
if (t>0)
{
for (long long i=14;i>=0;i--)
{
if (t>=(1<<i))
{
t=t-(1<<i);
ans=max(submax[y][i],ans);
ans=max(ans,maxx-mi[y][i]);
maxx=max(maxx,ma[y][i]);
y=anc[y][i];
}
}
}
ans=max(ans,maxx-minn);
}
int main()
{
scanf("%lld",&n);
for (long long i=1;i<=n;i++)
scanf("%lld",&price[i]);
for (long long i=1;i<=n-1;i++)
{
scanf("%lld%lld",&x,&y);
addedge(x,y);
addedge(y,x);
}
dis[0]=-1;
dfs(1);
for (long long i=1;i<=14;i++)
for (long long j=1;j<=n;j++)
{
anc[j][i]=anc[anc[j][i-1]][i-1];
ma[j][i]=max(ma[j][i-1],ma[anc[j][i-1]][i-1]);
mi[j][i]=min(mi[j][i-1],mi[anc[j][i-1]][i-1]);
premax[j][i]=max(max(premax[j][i-1],premax[anc[j][i-1]][i-1]),ma[anc[j][i-1]][i-1]-mi[j][i-1]);
submax[j][i]=max(max(submax[j][i-1],submax[anc[j][i-1]][i-1]),ma[j][i-1]-mi[anc[j][i-1]][i-1]);
}
scanf("%lld",&m);
for (long long i=1;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
jump();
printf("%lld\n",ans);
}
return 0;
}
浙公网安备 33010602011771号