题意:给定n个城市,每两个城市之间有且仅有一条路。货物在各个城市的价格不同,在一条路径中,
思路:利用LCA倍增法求解过程,同时求出最大利润。
在LCA倍增法中,设fa[x][i]表示,x点的2^i的祖宗节点。
同理设up[x][i]为从x走到fa[x][i]过程能获得的最大利益
设down[x][i]为从fa[x][i]走到x过程的最大利益
设fma[x][i]为x和fa[x][i]之间的最大价格
设fmi[x][i]为x和fa[x][i]之间的最小价格
在倍增法过程就能快速求解出最大利益
注意维护过程
#include<cstring>
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define fma fmaxxxx
const int INF=0x3f3f3f3f;
const int N=50500;
int dep[N],fa[N][20],fma[N][20],fmi[N][20],up[N][20],down[N][20],val[N];
int n,m;
vector<int>g[N];
void dfs(int x,int pa,int d)
{
dep[x]=d;
for(int i=0;i<g[x].size();i++)
{
int y=g[x][i];
if(y==pa)continue;
fa[y][0]=x;
fma[y][0]=max(val[x],val[y]);
fmi[y][0]=min(val[x],val[y]);
up[y][0]=max(0,val[x]-val[y]);
down[y][0]=max(0,val[y]-val[x]);
dfs(y,x,d+1);
}
}
void init()
{
for(int j=1;j<=m;j++)
{
for(int i=1;i<=n;i++)
{
if(fa[i][j-1]<0){fa[i][j-1]=-1;continue;}
fa[i][j]=fa[fa[i][j-1]][j-1];
fma[i][j]=max(fma[i][j-1],fma[fa[i][j-1]][j-1]);
fmi[i][j]=min(fmi[i][j-1],fmi[fa[i][j-1]][j-1]);
up[i][j]=max(up[i][j-1],up[fa[i][j-1]][j-1]);
up[i][j]=max(up[i][j],fma[fa[i][j-1]][j-1]-fmi[i][j-1]);
down[i][j]=max(down[i][j-1],down[fa[i][j-1]][j-1]);
down[i][j]=max(down[i][j],fma[i][j-1]-fmi[fa[i][j-1]][j-1]);
}
}
}
int LCA(int x,int y)
{
int ans=0,mixx=val[x],maxx=val[y];
if(dep[x]>dep[y])
{
for(int i=0;i<=m;i++)
{
if((dep[x]-dep[y])&(1<<i))
{
ans=max(ans,up[x][i]);
ans=max(ans,fma[x][i]-mixx);
mixx=min(mixx,fmi[x][i]);
x=fa[x][i];
}
}
}
else
{
for(int i=0;i<=m;i++)
{
if((dep[y]-dep[x])&(1<<i))
{
ans=max(ans,down[y][i]);
ans=max(ans,maxx-fmi[y][i]);
maxx=max(maxx,fma[y][i]);
y=fa[y][i];
}
}
}
if(x==y)
{
;
}
else
{
for(int i=m;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])
{
ans=max(ans,up[x][i]);
ans=max(ans,fma[x][i]-mixx);
mixx=min(mixx,fmi[x][i]);
ans=max(ans,down[y][i]);
ans=max(ans,maxx-fmi[y][i]);
maxx=max(maxx,fma[y][i]);
x=fa[x][i];
y=fa[y][i];
}
}
mixx=min(mixx,fmi[x][0]);
maxx=max(maxx,fma[y][0]);
}
ans=max(ans,maxx-mixx);
printf("%d\n",ans);
return fa[x][0];
}
int main()
{
int x,y;
while(scanf("%d",&n)!=EOF)
{
m=0;
for(int i=1;i<=n;i++)
g[i].clear();
while(n>=(1<<m))m++;
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
fa[1][0]=-1;
dfs(1,-1,1);
init();
int TAT;
scanf("%d",&TAT);
while(TAT--)
{
scanf("%d%d",&x,&y);
int ret=LCA(x,y);
//-cout<<ret<<" **"<<endl;
}
}
return 0;
}