要是求路径MAX、MIN可能大家直接树剖了…
但是本题要求的是一条单向路径,且要先买后卖
于是我们要想方设法优化暴力模拟沿路径走的这一过程
于是各位想到了(倍增!)
我们设
maxx[i][j] 为从i向上走(1 << j)步所经过的最大点权
minn[i][j]为从i向上走(1 << j)步所经过的最小点权
up[i][j] 为从i向上走(1 << j)步的最大答案
minn[i][j]为向下走(1 << j)步到i的最大答案
(刚刚已经阐述了,up[i][j]和minn[i][j]可能不同)
AC Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define rg register
#define il inline
#define ll long long
#define maxn 100005
using namespace std;
il int read(){rg int x = 0 , w = 1;rg char ch = getchar();while (ch < '0' || ch > '9'){if (ch == '-') w = -1;ch = getchar();}while (ch >= '0' && ch <= '9'){x = (x << 3) + (x << 1) + ch - '0';ch = getchar();}return x * w;}
int f[maxn][21] , up[maxn][21] , down[maxn][21] , maxx[maxn][21] , minn[maxn][21];
int dep[maxn] , p[maxn];
struct edge{
int to , next;
}e[maxn << 2];
int head[maxn] , cnt;
void add(int u , int v){
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void dfs(int u , int fa){
dep[u] = dep[fa] + 1;
f[u][0] = fa;
maxx[u][0] = max(p[u] , p[fa]);
minn[u][0] = min(p[u] , p[fa]);
up[u][0] = p[fa] - p[u];
down[u][0] = p[u] - p[fa];
for (rg int i = 1 ; i <= 17 ; ++i)
f[u][i] = f[f[u][i - 1]][i - 1];
for (rg int i = 1 ; i <= 17 ; ++i){
maxx[u][i] = max(maxx[u][i - 1] , maxx[f[u][i - 1]][i - 1]);
minn[u][i] = min(minn[u][i - 1] , minn[f[u][i - 1]][i - 1]);
up[u][i] = max(max(up[u][i - 1] , up[f[u][i - 1]][i - 1]) , maxx[f[u][i - 1]][i - 1] - minn[u][i - 1]);
down[u][i] = max(max(down[u][i - 1] , down[f[u][i - 1]][i - 1]) , maxx[u][i - 1] - minn[f[u][i - 1]][i - 1]);
}
for (rg int i = head[u] ; i ; i = e[i].next){
rg int to = e[i].to;
if (to != fa)
dfs(to , u);
}
}
int lca(int a , int b){
if (dep[a] > dep[b]) a ^= b , b ^= a , a ^= b;
for (rg int i = 17 ; i >= 0 ; --i)
if (dep[b] - dep[a] >= (1 << i))
b = f[b][i];
if (a == b) return a;
for (rg int i = 17 ; i >= 0 ; --i)
if (f[a][i] != f[b][i])
a = f[a][i] , b = f[b][i];
return f[a][0];
}
int query1(int a , int lca0 , int &minl){
rg int ans = -1;
minl = 9999999;
for (rg int i = 17 ; i >= 0 ; --i)
if (dep[a] - dep[lca0] >= (1 << i)){
ans = max(ans , max(up[a][i] , maxx[a][i] - minl));
minl = min(minl , minn[a][i]);
a = f[a][i];
}
return ans;
}
int query2(int b , int lca0 , int &maxl){
rg int ans = -1;
maxl = -1;
for (rg int i = 17 ; i >= 0 ; --i)
if (dep[b] - dep[lca0] >= (1 << i)){
ans = max(ans , max(down[b][i] , maxl - minn[b][i]));
maxl = max(maxl , maxx[b][i]);
b = f[b][i];
}
return ans;
}
int main(){
rg int n = read() , u , v , w;
for (rg int i = 1 ; i <= n ; ++i)
p[i] = read();
dep[1] = 1;
for (rg int i = 1 ; i < n ; ++i){
rg int u = read() , v = read();
add(u , v);add(v , u);
}
dfs(1 , 0);
rg int q = read() , maxl , minl , ans;
for (rg int i = 1 ; i <= q ; ++i){
u = read() , v = read();
ans = -1;
rg int lcaa = lca(u , v);
rg int x1 = query1(u , lcaa , minl) , x2 = query2(v , lcaa , maxl);
printf("%d\n" , max(max(max(x1 , x2) , maxl - minl) , 0));
}
return 0;
}