← Home
```go
package main

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

type TrieNode struct {
	child [2]int32
	count int32
}

const MAXN = 200005

var (
	D        = make([]int, MAXN)
	depth    = make([]int8, MAXN)
	head     = make([]int, MAXN)
	to       = make([]int, MAXN*2)
	weight   = make([]int, MAXN*2)
	nxt      = make([]int, MAXN*2)
	trie     = make([]TrieNode, 6500000)
	allocIdx int32
	root0    int32
	root1    int32
)

func newNode() int32 {
	allocIdx++
	if int(allocIdx) >= len(trie) {
		trie = append(trie, TrieNode{})
	} else {
		trie[allocIdx] = TrieNode{}
	}
	return allocIdx
}

func insert(root int32, val int) {
	curr := root
	trie[curr].count++
	for i := 29; i >= 0; i-- {
		bit := (val >> i) & 1
		if trie[curr].child[bit] == 0 {
			trie[curr].child[bit] = newNode()
		}
		curr = trie[curr].child[bit]
		trie[curr].count++
	}
}

func remove(root int32, val int) {
	curr := root
	trie[curr].count--
	for i := 29; i >= 0; i-- {
		bit := (val >> i) & 1
		curr = trie[curr].child[bit]
		trie[curr].count--
	}
}

func maxXor(root int32, val int) int {
	if trie[root].count == 0 {
		return -1
	}
	curr := root
	ans := 0
	for i := 29; i >= 0; i-- {
		bit := (val >> i) & 1
		alt := 1 - bit
		if trie[curr].child[alt] != 0 && trie[trie[curr].child[alt]].count > 0 {
			ans |= (1 << i)
			curr = trie[curr].child[alt]
		} else {
			curr = trie[curr].child[bit]
		}
	}
	return ans
}

func dfs(u, p, d, xorSum int) {
	depth[u] = int8(d & 1)
	D[u] = xorSum
	if depth[u] == 0 {
		insert(root0, xorSum)
	} else {
		insert(root1, xorSum)
	}
	for e := head[u]; e != 0; e = nxt[e] {
		v := to[e]
		if v != p {
			dfs(v, u, d+1, xorSum^weight[e])
		}
	}
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	buffer := make([]byte, 1024*1024)
	scanner.Buffer(buffer, 1024*1024*10)

	readInt := func() int {
		scanner.Scan()
		s := scanner.Bytes()
		v := 0
		for _, b := range s {
			v = v*10 + int(b-'0')
		}
		return v
	}

	readOp := func() byte {
		scanner.Scan()
		return scanner.Bytes()[0]
	}

	if !scanner.Scan() {
		return
	}
	s := scanner.Bytes()
	t := 0
	for _, b := range s {
		t = t*10 + int(b-'0')
	}

	writer := bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	for tc := 0; tc < t; tc++ {
		n := readInt()
		m := readInt()

		for i := 1; i <= n; i++ {
			head[i] = 0
		}
		edgeCnt := 0
		addEdge := func(u, v, w int) {
			edgeCnt++
			to[edgeCnt] = v
			weight[edgeCnt] = w
			nxt[edgeCnt] = head[u]
			head[u] = edgeCnt
		}

		for i := 0; i < n-1; i++ {
			u := readInt()
			v := readInt()
			w := readInt()
			addEdge(u, v, w)
			addEdge(v, u, w)
		}

		allocIdx = 0
		trie[0] = TrieNode{}
		root0 = newNode()
		root1 = newNode()

		dfs(1, 0, 0, 0)

		lazy := 0
		for i := 0; i < m; i++ {
			op := readOp()
			if op == '^' {
				y := readInt()
				lazy ^= y
			} else {
				v := readInt()
				x := readInt()

				var currDv int
				if depth[v] == 0 {
					currDv = D[v]
				} else {
					currDv = D[v] ^ lazy
				}

				if depth[v] == 0 {
					remove(root0, D[v])
				} else {
					remove(root1, D[v])
				}

				q0 := currDv ^ x
				q1 := currDv ^ x ^ lazy

				ans := -1
				if res := maxXor(root0, q0); res != -1 {
					if res > ans {
						ans = res
					}
				}
				if res := maxXor(root1, q1); res != -1 {
					if res > ans {
						ans = res
					}
				}

				fmt.Fprint(writer, ans, " ")

				if depth[v] == 0 {
					insert(root0, D[v])
				} else {
					insert(root1, D[v])
				}
			}
		}
		fmt.Fprintln(writer)
	}
}
```