package main
import (
"io"
"os"
)
type Scanner struct {
buf []byte
pos int
}
func NewScanner() *Scanner {
b, _ := io.ReadAll(os.Stdin)
return &Scanner{buf: b, pos: 0}
}
func (s *Scanner) nextInt() int {
for s.pos < len(s.buf) && s.buf[s.pos] <= ' ' {
s.pos++
}
if s.pos >= len(s.buf) {
return 0
}
res := 0
for s.pos < len(s.buf) && s.buf[s.pos] > ' ' {
res = res*10 + int(s.buf[s.pos]-'0')
s.pos++
}
return res
}
type Writer struct {
buf []byte
}
func NewWriter() *Writer {
return &Writer{buf: make([]byte, 0, 1024*1024*10)}
}
func (w *Writer) printInt(n int) {
if n == -1 {
w.buf = append(w.buf, '-', '1', '\n')
return
}
if n == 0 {
w.buf = append(w.buf, '0', '\n')
return
}
var rev [20]byte
pos := 0
for n > 0 {
rev[pos] = byte(n%10) + '0'
n /= 10
pos++
}
for i := pos - 1; i >= 0; i-- {
w.buf = append(w.buf, rev[i])
}
w.buf = append(w.buf, '\n')
}
func (w *Writer) flush() {
os.Stdout.Write(w.buf)
}
const MAX_NODES = 10000000
const MAX_N = 300005
type Node struct {
ls int
rs int
hash uint64
}
var nodes [MAX_NODES]Node
var nodeCnt int
var up [MAX_N][20]int
var depth [MAX_N]int
var roots [MAX_N]int
var a [MAX_N]int
var H [MAX_N]uint64
var head [MAX_N]int
var next []int
var to []int
var seed uint64 = 0x1234567890abcdef
func randUint64() uint64 {
seed ^= seed << 13
seed ^= seed >> 7
seed ^= seed << 17
return seed
}
func newNode() int {
nodeCnt++
return nodeCnt
}
func insert(prev, L, R, idx int) int {
curr := newNode()
nodes[curr] = nodes[prev]
nodes[curr].hash ^= H[idx]
if L == R {
return curr
}
mid := L + (R-L)/2
if idx <= mid {
nodes[curr].ls = insert(nodes[prev].ls, L, mid, idx)
} else {
nodes[curr].rs = insert(nodes[prev].rs, mid+1, R, idx)
}
return curr
}
func addEdge(u, v int) {
to = append(to, v)
next = append(next, head[u])
head[u] = len(to) - 1
}
var n, q int
func dfs(u, p, d int) {
up[u][0] = p
depth[u] = d
roots[u] = insert(roots[p], 1, n, a[u])
for i := 1; i < 20; i++ {
up[u][i] = up[up[u][i-1]][i-1]
}
for e := head[u]; e != -1; e = next[e] {
v := to[e]
if v != p {
dfs(v, u, d+1)
}
}
}
func getLCA(u, v int) int {
if depth[u] < depth[v] {
u, v = v, u
}
diff := depth[u] - depth[v]
for i := 0; i < 20; i++ {
if (diff & (1 << i)) != 0 {
u = up[u][i]
}
}
if u == v {
return u
}
for i := 19; i >= 0; i-- {
if up[u][i] != up[v][i] {
u = up[u][i]
v = up[v][i]
}
}
return up[u][0]
}
func query(nu, nv, nlca, np, L, R, l, r int) int {
hash := nodes[nu].hash ^ nodes[nv].hash ^ nodes[nlca].hash ^ nodes[np].hash
if hash == 0 {
return -1
}
if L == R {
return L
}
mid := L + (R-L)/2
if l <= mid {
res := query(nodes[nu].ls, nodes[nv].ls, nodes[nlca].ls, nodes[np].ls, L, mid, l, r)
if res != -1 {
return res
}
}
if r > mid {
res := query(nodes[nu].rs, nodes[nv].rs, nodes[nlca].rs, nodes[np].rs, mid+1, R, l, r)
if res != -1 {
return res
}
}
return -1
}
func main() {
scanner := NewScanner()
n = scanner.nextInt()
q = scanner.nextInt()
for i := 1; i <= n; i++ {
a[i] = scanner.nextInt()
H[i] = randUint64()
head[i] = -1
}
next = make([]int, 0, 2*n)
to = make([]int, 0, 2*n)
for i := 1; i < n; i++ {
u := scanner.nextInt()
v := scanner.nextInt()
addEdge(u, v)
addEdge(v, u)
}
dfs(1, 0, 0)
writer := NewWriter()
for i := 0; i < q; i++ {
u := scanner.nextInt()
v := scanner.nextInt()
l := scanner.nextInt()
r := scanner.nextInt()
lca := getLCA(u, v)
p := up[lca][0]
res := query(roots[u], roots[v], roots[lca], roots[p], 1, n, l, r)
writer.printInt(res)
}
writer.flush()
}