← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReaderSize(os.Stdin, 1<<20)
	writer := bufio.NewWriterSize(os.Stdout, 1<<20)
	defer writer.Flush()

	readInt := func() int {
		var n int
		var c byte
		for {
			c, _ = reader.ReadByte()
			if c >= '0' && c <= '9' {
				break
			}
		}
		for {
			n = n*10 + int(c-'0')
			c, _ = reader.ReadByte()
			if c < '0' || c > '9' {
				break
			}
		}
		return n
	}

	n := readInt()
	adj := make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		u := readInt()
		v := readInt()
		adj[u] = append(adj[u], v)
		adj[v] = append(adj[v], u)
	}

	timer := 0
	in := make([]int, n+1)
	out := make([]int, n+1)
	nodeAt := make([]int, n+1)
	depth := make([]int, n+1)
	up := make([][18]int, n+1)
	first := make([]int, n+1)
	eulerLCA := make([]int, 0, 2*n)
	depthLCA := make([]int, 0, 2*n)

	var dfs func(u, p, d int)
	dfs = func(u, p, d int) {
		timer++
		in[u] = timer
		nodeAt[timer] = u
		depth[u] = d
		up[u][0] = p
		if p == 0 {
			up[u][0] = 1
		}
		for i := 1; i < 18; i++ {
			up[u][i] = up[up[u][i-1]][i-1]
		}
		first[u] = len(eulerLCA)
		eulerLCA = append(eulerLCA, u)
		depthLCA = append(depthLCA, d)

		for _, v := range adj[u] {
			if v != p {
				dfs(v, u, d+1)
				eulerLCA = append(eulerLCA, u)
				depthLCA = append(depthLCA, d)
			}
		}
		out[u] = timer
	}
	dfs(1, 0, 0)

	m_len := len(eulerLCA)
	log2 := make([]int, m_len+1)
	if m_len >= 1 {
		log2[1] = 0
	}
	for i := 2; i <= m_len; i++ {
		log2[i] = log2[i/2] + 1
	}
	K := log2[m_len] + 1
	st := make([][]int, K)
	for i := 0; i < K; i++ {
		st[i] = make([]int, m_len)
	}
	for i := 0; i < m_len; i++ {
		st[0][i] = i
	}
	for i := 1; i < K; i++ {
		for j := 0; j+(1<<i) <= m_len; j++ {
			idx1 := st[i-1][j]
			idx2 := st[i-1][j+(1<<(i-1))]
			if depthLCA[idx1] < depthLCA[idx2] {
				st[i][j] = idx1
			} else {
				st[i][j] = idx2
			}
		}
	}

	getLCA := func(u, v int) int {
		if u == v {
			return u
		}
		l := first[u]
		r := first[v]
		if l > r {
			l, r = r, l
		}
		k := log2[r-l+1]
		idx1 := st[k][l]
		idx2 := st[k][r-(1<<k)+1]
		if depthLCA[idx1] < depthLCA[idx2] {
			return eulerLCA[idx1]
		}
		return eulerLCA[idx2]
	}

	getDist := func(u, v int) int {
		return depth[u] + depth[v] - 2*depth[getLCA(u, v)]
	}

	type Node struct {
		u, v int
		d    int
	}

	merge := func(a, b Node) Node {
		if a.u == 0 {
			return b
		}
		if b.u == 0 {
			return a
		}
		best := a
		if b.d > best.d {
			best = b
		}
		pairs := [4][2]int{{a.u, b.u}, {a.u, b.v}, {a.v, b.u}, {a.v, b.v}}
		for _, p := range pairs {
			d := getDist(p[0], p[1])
			if d > best.d {
				best.u = p[0]
				best.v = p[1]
				best.d = d
			}
		}
		return best
	}

	tree := make([]Node, 4*n+1)
	var build func(idx, l, r int)
	build = func(idx, l, r int) {
		if l == r {
			v := nodeAt[l]
			tree[idx] = Node{v, v, 0}
			return
		}
		mid := (l + r) / 2
		build(2*idx, l, mid)
		build(2*idx+1, mid+1, r)
		tree[idx] = merge(tree[2*idx], tree[2*idx+1])
	}
	if n > 0 {
		build(1, 1, n)
	}

	var queryST func(idx, l, r, ql, qr int) Node
	queryST = func(idx, l, r, ql, qr int) Node {
		if ql > r || qr < l {
			return Node{0, 0, -1}
		}
		if ql <= l && r <= qr {
			return tree[idx]
		}
		mid := (l + r) / 2
		resL := queryST(2*idx, l, mid, ql, qr)
		resR := queryST(2*idx+1, mid+1, r, ql, qr)
		return merge(resL, resR)
	}

	getComponent := func(z int, isSubtree bool) Node {
		if isSubtree {
			return queryST(1, 1, n, in[z], out[z])
		} else {
			res := Node{0, 0, -1}
			if in[z] > 1 {
				res = merge(res, queryST(1, 1, n, 1, in[z]-1))
			}
			if out[z] < n {
				res = merge(res, queryST(1, 1, n, out[z]+1, n))
			}
			return res
		}
	}

	getKthNode := func(u, v, k int) int {
		lca := getLCA(u, v)
		distU := depth[u] - depth[lca]
		if k <= distU {
			curr := u
			for i := 17; i >= 0; i-- {
				if (k & (1 << i)) != 0 {
					curr = up[curr][i]
				}
			}
			return curr
		} else {
			distV := depth[v] - depth[lca]
			rem := distU + distV - k
			curr := v
			for i := 17; i >= 0; i-- {
				if (rem & (1 << i)) != 0 {
					curr = up[curr][i]
				}
			}
			return curr
		}
	}

	m := readInt()
	for i := 0; i < m; i++ {
		u := readInt()
		v := readInt()

		d := getDist(u, v)
		k := (d - 1) / 2
		w := getKthNode(u, v, k)
		z := getKthNode(u, v, k+1)

		var nodeTu, nodeTv Node
		if up[w][0] == z {
			nodeTu = getComponent(w, true)
			nodeTv = getComponent(w, false)
		} else {
			nodeTu = getComponent(z, false)
			nodeTv = getComponent(z, true)
		}

		maxDu := getDist(u, nodeTu.u)
		if d2 := getDist(u, nodeTu.v); d2 > maxDu {
			maxDu = d2
		}

		maxDv := getDist(v, nodeTv.u)
		if d2 := getDist(v, nodeTv.v); d2 > maxDv {
			maxDv = d2
		}

		ans := maxDu
		if maxDv > ans {
			ans = maxDv
		}
		fmt.Fprintln(writer, ans)
	}
}
```