← Home
package main

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

const INF int64 = 100000000000000000

type Node struct {
	minW int64
	id   int
	lazy int64
}

var (
	n, m, q int
	adj     [][]int
	girls   [][]int
	head    []int

	depth, parent, sz, top, tin, tout, rev_tin []int
	timer int

	tree []Node
)

var scanner *bufio.Scanner

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

func readInt() int {
	scanner.Scan()
	v, _ := strconv.Atoi(scanner.Text())
	return v
}

func dfs1(u, p, d int) {
	depth[u] = d
	parent[u] = p
	sz[u] = 1
	for _, v := range adj[u] {
		if v != p {
			dfs1(v, u, d+1)
			sz[u] += sz[v]
		}
	}
}

func dfs2(u, p, top_node int) {
	top[u] = top_node
	tin[u] = timer
	rev_tin[timer] = u
	timer++

	heavy_child := -1
	heavy_sz := -1
	for _, v := range adj[u] {
		if v != p && sz[v] > heavy_sz {
			heavy_sz = sz[v]
			heavy_child = v
		}
	}
	if heavy_child != -1 {
		dfs2(heavy_child, u, top_node)
	}
	for _, v := range adj[u] {
		if v != p && v != heavy_child {
			dfs2(v, u, v)
		}
	}
	tout[u] = timer - 1
}

func pushUp(node int) {
	lc, rc := node*2, node*2+1
	if tree[lc].minW < tree[rc].minW {
		tree[node].minW = tree[lc].minW
		tree[node].id = tree[lc].id
	} else if tree[lc].minW > tree[rc].minW {
		tree[node].minW = tree[rc].minW
		tree[node].id = tree[rc].id
	} else {
		if tree[lc].id < tree[rc].id {
			tree[node].id = tree[lc].id
		} else {
			tree[node].id = tree[rc].id
		}
		tree[node].minW = tree[lc].minW
	}
}

func pushDown(node int) {
	if tree[node].lazy != 0 {
		lz := tree[node].lazy
		tree[node*2].minW += lz
		tree[node*2].lazy += lz
		tree[node*2+1].minW += lz
		tree[node*2+1].lazy += lz
		tree[node].lazy = 0
	}
}

func build(node, l, r int) {
	if l == r {
		u := rev_tin[l]
		if len(girls[u]) > 0 {
			tree[node] = Node{minW: int64(girls[u][0]), id: u, lazy: 0}
		} else {
			tree[node] = Node{minW: INF, id: u, lazy: 0}
		}
		return
	}
	mid := (l + r) / 2
	build(node*2, l, mid)
	build(node*2+1, mid+1, r)
	pushUp(node)
}

func update_point(node, l, r, idx int, diff int64) {
	if l == r {
		tree[node].minW += diff
		return
	}
	pushDown(node)
	mid := (l + r) / 2
	if idx <= mid {
		update_point(node*2, l, mid, idx, diff)
	} else {
		update_point(node*2+1, mid+1, r, idx, diff)
	}
	pushUp(node)
}

func update_range(node, l, r, ql, qr int, val int64) {
	if ql <= l && r <= qr {
		tree[node].minW += val
		tree[node].lazy += val
		return
	}
	pushDown(node)
	mid := (l + r) / 2
	if ql <= mid {
		update_range(node*2, l, mid, ql, qr, val)
	}
	if qr > mid {
		update_range(node*2+1, mid+1, r, ql, qr, val)
	}
	pushUp(node)
}

func query(node, l, r, ql, qr int) (int64, int) {
	if ql <= l && r <= qr {
		return tree[node].minW, tree[node].id
	}
	pushDown(node)
	mid := (l + r) / 2
	resW, resId := int64(INF), int(1e9)
	if ql <= mid {
		w, id := query(node*2, l, mid, ql, qr)
		if w < resW || (w == resW && id < resId) {
			resW, resId = w, id
		}
	}
	if qr > mid {
		w, id := query(node*2+1, mid+1, r, ql, qr)
		if w < resW || (w == resW && id < resId) {
			resW, resId = w, id
		}
	}
	return resW, resId
}

func query_path(u, v int) (int64, int) {
	resW := int64(INF)
	resId := int(1e9)
	for top[u] != top[v] {
		if depth[top[u]] < depth[top[v]] {
			u, v = v, u
		}
		w, id := query(1, 0, n-1, tin[top[u]], tin[u])
		if w < resW || (w == resW && id < resId) {
			resW, resId = w, id
		}
		u = parent[top[u]]
	}
	if depth[u] > depth[v] {
		u, v = v, u
	}
	w, id := query(1, 0, n-1, tin[u], tin[v])
	if w < resW || (w == resW && id < resId) {
		resW, resId = w, id
	}
	return resW, resId
}

func main() {
	n = readInt()
	m = readInt()
	q = readInt()

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

	girls = make([][]int, n+1)
	for i := 1; i <= m; i++ {
		c := readInt()
		girls[c] = append(girls[c], i)
	}

	head = make([]int, n+1)

	depth = make([]int, n+1)
	parent = make([]int, n+1)
	sz = make([]int, n+1)
	top = make([]int, n+1)
	tin = make([]int, n+1)
	tout = make([]int, n+1)
	rev_tin = make([]int, n+1)

	if n > 0 {
		dfs1(1, 0, 0)
		dfs2(1, 0, 1)
		tree = make([]Node, 4*n+1)
		build(1, 0, n-1)
	}

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

	ans := make([]int, 0, n)

	for i := 0; i < q; i++ {
		t := readInt()
		if t == 1 {
			v := readInt()
			u := readInt()
			k := readInt()
			ans = ans[:0]
			for j := 0; j < k; j++ {
				if n == 0 {
					break
				}
				minW, minId := query_path(v, u)
				if minW >= INF/2 {
					break
				}
				gId := girls[minId][head[minId]]
				ans = append(ans, gId)
				head[minId]++
				var diff int64
				if head[minId] < len(girls[minId]) {
					diff = int64(girls[minId][head[minId]] - girls[minId][head[minId]-1])
				} else {
					diff = INF
				}
				update_point(1, 0, n-1, tin[minId], diff)
			}
			fmt.Fprintf(out, "%d", len(ans))
			for _, g := range ans {
				fmt.Fprintf(out, " %d", g)
			}
			fmt.Fprintln(out)
		} else {
			v := readInt()
			k := readInt()
			if n > 0 {
				update_range(1, 0, n-1, tin[v], tout[v], int64(k))
			}
		}
	}
}