← Home
```go
package main

import (
	"bufio"
	"io"
	"os"
	"strconv"
)

type Line struct {
	m, c int64
}

type Node struct {
	ln         Line
	left, right *Node
}

type LiChao struct {
	root     *Node
	l, r int64
}

func eval(ln Line, x int64) int64 {
	return ln.m*x + ln.c
}

func (lc *LiChao) add(n *Node, l, r int64, nw Line) *Node {
	if n == nil {
		return &Node{ln: nw}
	}
	m := (l + r) >> 1
	leftBetter := eval(nw, l) < eval(n.ln, l)
	midBetter := eval(nw, m) < eval(n.ln, m)
	if midBetter {
		n.ln, nw = nw, n.ln
	}
	if l == r {
		return n
	}
	if leftBetter != midBetter {
		n.left = lc.add(n.left, l, m, nw)
	} else {
		n.right = lc.add(n.right, m+1, r, nw)
	}
	return n
}

func (lc *LiChao) AddLine(ln Line) {
	lc.root = lc.add(lc.root, lc.l, lc.r, ln)
}

func (lc *LiChao) query(n *Node, l, r, x int64) int64 {
	res := eval(n.ln, x)
	if l == r {
		return res
	}
	m := (l + r) >> 1
	if x <= m && n.left != nil {
		v := lc.query(n.left, l, m, x)
		if v < res {
			res = v
		}
	} else if x > m && n.right != nil {
		v := lc.query(n.right, m+1, r, x)
		if v < res {
			res = v
		}
	}
	return res
}

func (lc *LiChao) Query(x int64) int64 {
	return lc.query(lc.root, lc.l, lc.r, x)
}

type Hull struct {
	lc    *LiChao
	lines []Line
}

func NewHull(l, r int64) *Hull {
	return &Hull{lc: &LiChao{l: l, r: r}, lines: make([]Line, 0)}
}

func (h *Hull) Add(line Line) {
	h.lc.AddLine(line)
	h.lines = append(h.lines, line)
}

func (h *Hull) Merge(other *Hull) {
	if other == nil || len(other.lines) == 0 {
		return
	}
	for _, ln := range other.lines {
		h.Add(ln)
	}
}

var data []byte
var idx int

func nextInt64() int64 {
	n := len(data)
	for idx < n && (data[idx] < '0' || data[idx] > '9') && data[idx] != '-' {
		idx++
	}
	sign := int64(1)
	if idx < n && data[idx] == '-' {
		sign = -1
		idx++
	}
	val := int64(0)
	for idx < n && data[idx] >= '0' && data[idx] <= '9' {
		val = val*10 + int64(data[idx]-'0')
		idx++
	}
	return val * sign
}

func main() {
	reader := bufio.NewReaderSize(os.Stdin, 1<<20)
	bs, _ := io.ReadAll(reader)
	data = bs
	n := int(nextInt64())

	a := make([]int64, n+1)
	b := make([]int64, n+1)
	minA, maxA := int64(0), int64(0)
	for i := 1; i <= n; i++ {
		a[i] = nextInt64()
		if i == 1 {
			minA, maxA = a[i], a[i]
		} else {
			if a[i] < minA {
				minA = a[i]
			}
			if a[i] > maxA {
				maxA = a[i]
			}
		}
	}
	for i := 1; i <= n; i++ {
		b[i] = nextInt64()
	}
	g := make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		u := int(nextInt64())
		v := int(nextInt64())
		g[u] = append(g[u], v)
		g[v] = append(g[v], u)
	}

	parent := make([]int, n+1)
	order := make([]int, 0, n)
	stack := make([]int, 0, n)
	stack = append(stack, 1)
	parent[1] = 0
	for len(stack) > 0 {
		v := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		order = append(order, v)
		for _, w := range g[v] {
			if w == parent[v] {
				continue
			}
			parent[w] = v
			stack = append(stack, w)
		}
	}

	dp := make([]int64, n+1)
	hulls := make([]*Hull, n+1)

	for i := len(order) - 1; i >= 0; i-- {
		v := order[i]
		var base *Hull
		for _, w := range g[v] {
			if w == parent[v] {
				continue
			}
			h := hulls[w]
			if h == nil {
				continue
			}
			if base == nil || len(h.lines) > len(base.lines) {
				base = h
			}
		}
		for _, w := range g[v] {
			if w == parent[v] {
				continue
			}
			h := hulls[w]
			if h == nil || h == base {
				continue
			}
			base.Merge(h)
			hulls[w] = nil
		}

		if base == nil || len(base.lines) == 0 {
			dp[v] = 0
		} else {
			dp[v] = base.lc.Query(a[v])
		}

		curLine := Line{m: b[v], c: dp[v]}
		if base == nil {
			base = NewHull(minA, maxA)
		}
		base.Add(curLine)
		hulls[v] = base

		for _, w := range g[v] {
			if w == parent[v] {
				continue
			}
			hulls[w] = nil
		}
	}

	out := bufio.NewWriterSize(os.Stdout, 1<<20)
	for i := 1; i <= n; i++ {
		if i > 1 {
			out.WriteByte(' ')
		}
		out.WriteString(strconv.FormatInt(dp[i], 10))
	}
	out.WriteByte('\n')
	out.Flush()
}
```