← Home
package main

import (
	"io"
	"os"
)

type Scanner struct {
	buf []byte
	pos int
}

func NewScanner() *Scanner {
	buf, _ := io.ReadAll(os.Stdin)
	return &Scanner{buf: buf, 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
}

var (
	head    []int
	to      []int
	next    []int
	edgeCnt int

	depth []int
	euler []int
	first []int
	timer int

	st   [][]int
	log2 []int

	tree []Node
)

func addEdge(u, v int) {
	edgeCnt++
	to[edgeCnt] = v
	next[edgeCnt] = head[u]
	head[u] = edgeCnt
}

func dfs(u, p, d int) {
	depth[u] = d
	timer++
	euler[timer] = u
	first[u] = timer
	for e := head[u]; e != 0; e = next[e] {
		v := to[e]
		if v != p {
			dfs(v, u, d+1)
			timer++
			euler[timer] = u
		}
	}
}

func buildRMQ() {
	M := timer
	log2 = make([]int, M+1)
	log2[1] = 0
	for i := 2; i <= M; i++ {
		log2[i] = log2[i/2] + 1
	}

	K := log2[M] + 1
	st = make([][]int, K)
	for i := 0; i < K; i++ {
		st[i] = make([]int, M+1)
	}

	for i := 1; i <= M; i++ {
		st[0][i] = euler[i]
	}

	for j := 1; j < K; j++ {
		for i := 1; i+(1<<j)-1 <= M; i++ {
			u := st[j-1][i]
			v := st[j-1][i+(1<<(j-1))]
			if depth[u] < depth[v] {
				st[j][i] = u
			} else {
				st[j][i] = v
			}
		}
	}
}

func getLCA(u, v int) int {
	l := first[u]
	r := first[v]
	if l > r {
		l, r = r, l
	}
	j := log2[r-l+1]
	n1 := st[j][l]
	n2 := st[j][r-(1<<j)+1]
	if depth[n1] < depth[n2] {
		return n1
	}
	return n2
}

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

type Node struct {
	u, v  int
	valid bool
}

func merge(A, B Node) Node {
	if !A.valid || !B.valid {
		return Node{valid: false}
	}
	if A.u == 0 {
		return B
	}
	if B.u == 0 {
		return A
	}

	pts := [4]int{A.u, A.v, B.u, B.v}
	maxD := -1
	bestU, bestV := 0, 0
	for i := 0; i < 4; i++ {
		for j := i + 1; j < 4; j++ {
			d := dist(pts[i], pts[j])
			if d > maxD {
				maxD = d
				bestU = pts[i]
				bestV = pts[j]
			}
		}
	}

	covers := true
	for i := 0; i < 4; i++ {
		if dist(bestU, pts[i])+dist(pts[i], bestV) != maxD {
			covers = false
			break
		}
	}
	if covers {
		return Node{u: bestU, v: bestV, valid: true}
	}
	return Node{valid: false}
}

func buildTree(curr, l, r int, pos []int) {
	if l == r {
		tree[curr] = Node{u: pos[l], v: pos[l], valid: true}
		return
	}
	mid := (l + r) / 2
	buildTree(curr*2, l, mid, pos)
	buildTree(curr*2+1, mid+1, r, pos)
	tree[curr] = merge(tree[curr*2], tree[curr*2+1])
}

func updateTree(curr, l, r, idx, nodeVal int) {
	if l == r {
		tree[curr] = Node{u: nodeVal, v: nodeVal, valid: true}
		return
	}
	mid := (l + r) / 2
	if idx <= mid {
		updateTree(curr*2, l, mid, idx, nodeVal)
	} else {
		updateTree(curr*2+1, mid+1, r, idx, nodeVal)
	}
	tree[curr] = merge(tree[curr*2], tree[curr*2+1])
}

func getMex(curr, l, r int, prefix Node) int {
	if l == r {
		merged := merge(prefix, tree[curr])
		if merged.valid {
			return l + 1
		}
		return l
	}

	mid := (l + r) / 2
	leftMerged := merge(prefix, tree[curr*2])
	if leftMerged.valid {
		return getMex(curr*2+1, mid+1, r, leftMerged)
	} else {
		return getMex(curr*2, l, mid, prefix)
	}
}

func query(n int) int {
	prefix := Node{u: 0, v: 0, valid: true}
	return getMex(1, 0, n-1, prefix)
}

func appendInt(b []byte, v int) []byte {
	if v == 0 {
		return append(b, '0')
	}
	var buf [20]byte
	i := 20
	for v > 0 {
		i--
		buf[i] = byte(v%10 + '0')
		v /= 10
	}
	return append(b, buf[i:]...)
}

func main() {
	scanner := NewScanner()
	n := scanner.nextInt()
	if n == 0 {
		return
	}

	p := make([]int, n+1)
	pos := make([]int, n)
	for i := 1; i <= n; i++ {
		p[i] = scanner.nextInt()
		pos[p[i]] = i
	}

	head = make([]int, n+1)
	to = make([]int, 2*n+10)
	next = make([]int, 2*n+10)
	edgeCnt = 0

	for i := 2; i <= n; i++ {
		d := scanner.nextInt()
		addEdge(d, i)
		addEdge(i, d)
	}

	depth = make([]int, n+1)
	first = make([]int, n+1)
	euler = make([]int, 2*n+10)
	timer = 0

	dfs(1, 0, 0)
	buildRMQ()

	tree = make([]Node, 4*n+10)
	buildTree(1, 0, n-1, pos)

	q := scanner.nextInt()

	out := make([]byte, 0, q*10)

	for k := 0; k < q; k++ {
		t := scanner.nextInt()
		if t == 1 {
			i := scanner.nextInt()
			j := scanner.nextInt()

			valI := p[i]
			valJ := p[j]

			p[i], p[j] = valJ, valI
			pos[valI], pos[valJ] = j, i

			updateTree(1, 0, n-1, valI, j)
			updateTree(1, 0, n-1, valJ, i)
		} else {
			ans := query(n)
			out = appendInt(out, ans)
			out = append(out, '\n')
		}
	}
	os.Stdout.Write(out)
}