Here's the structure:
function solve(tree, values, queries)
// Build HLD
buildHLD(root)
// Initialize segment tree with node values
arr := array of size n
for each node v
arr[pos[v]] := values[v]
buildSegmentTree(arr)
for each query
if query is update(u, newVal) then
segmentTreeUpdate(pos[u], newVal)
else // query is pathMax(u, v)
print pathMax(u, v)
The segment tree stores values at their HLD positions. Updates modify a single position. Queries combine multiple ranges.