题目链接:4395: 大家
题解:平常我们求lca有有数据f[i][v]表示是v往上方走pow(2,i)步的点,我们也可以用mx[i][v]表示是v往上方走pow(2,i)步的点所经过的最大值
转移方程见代码
#include<bits/stdc++.h> #include<set> #include<cstdio> #include<iomanip> #include<iostream> #include<string> #include<cstring> #include<algorithm> #define pb push_back #define mk make_pair #define ll long long #define fi first #define se second #define PI 3.14159265 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define eps 1e-7 #define pii pair<int,int> #define pll pair<ll,ll> typedef unsigned long long ull; const int mod=998244353; const ll inf=0x3f3f3f3f3f3f3f; const int maxn=2e4+5; using namespace std; int n,m,ma,f[20][maxn]; int a[maxn],mx[20][maxn],dep[maxn]; vector<int>g[maxn]; void dfs(int v,int fa) { for(int i=1;i<20;i++) { f[i][v]=f[i-1][f[i-1][v]]; mx[i][v]=max(mx[i-1][f[i-1][v]],mx[i-1][v]); } for(int i=0;i<g[v].size();i++) { int to=g[v][i]; if(to!=fa){ dep[to]=dep[v]+1; f[0][to]=v; mx[0][to]=a[v]; dfs(to,v); } } } int lca(int x,int y) { if(dep[x]<dep[y])swap(x,y); int t=dep[x]-dep[y],dx=0,dy=0; for(int k=0;k<20;k++) { if(t>>k&1) { dx=max(dx,mx[k][x]);x=f[k][x]; } } if(x==y) { ma=dx;return x; } for(int i=19;i>=0;i--) { if(f[i][x]!=f[i][y]) { dx=max(dx,mx[i][x]);x=f[i][x]; dy=max(dy,mx[i][y]);y=f[i][y]; } } ma=max(dx,dy); ma=max(ma,a[f[0][x]]); return f[0][x]; } int main() { ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n>>m; for(int i=0;i<n-1;i++) { int x,y; cin>>x>>y;g[x].pb(y);g[y].pb(x); } for(int j=1;j<=n;j++)cin>>a[j]; dfs(1,0); while(m--) { int x,y; cin>>x>>y;ma=0; if(dep[x]<dep[y])swap(x,y); if(x==y) { cout<<a[x]<<endl; } else if(lca(x,y)!=y) { cout<<-1<<endl; } else { cout<<max(ma,a[x])<<endl; } } return 0; }