#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
const long long inf = 1LL << 60;
int N, M, Q, cnt, timestamp, side[maxn], toit[maxn << 1], nxt[maxn << 1],
    L[maxn], R[maxn], redfn[maxn];
int dep[maxn], father[maxn], size[maxn], top[maxn];
long long tag[maxn << 2];
vector<int> people[maxn];
bool flag[maxn];
struct Node {
  long long key1;
  int key2, id;
  inline Node(long long _key1 = 0, int _key2 = 0, int _id = 0)
      : key1(_key1), key2(_key2), id(_id) {}
  friend inline Node operator+(const Node &a, const Node &b) {
    if (a.key1 != b.key1)
      return a.key1 < b.key1 ? a : b;
    else
      return a.key2 < b.key2 ? a : b;
  }
} tree[maxn << 2];
inline void add(int a, int b) {
  nxt[++cnt] = side[a];
  side[a] = cnt;
  toit[cnt] = b;
}
inline void ins(int a, int b) {
  add(a, b);
  add(b, a);
}
inline int gi() {
  char ch;
  int ret = 0, f = 1;
  do ch = getchar();
  while (!(ch >= '0' && ch <= '9') && ch != '-');
  if (ch == '-') f = -1, ch = getchar();
  do ret = ret * 10 + ch - '0', ch = getchar();
  while (ch >= '0' && ch <= '9');
  return ret * f;
}
inline void dfs(int now) {
  size[now] = 1;
  for (int i = side[now]; i; i = nxt[i])
    if (toit[i] != father[now]) {
      father[toit[i]] = now;
      dep[toit[i]] = dep[now] + 1;
      dfs(toit[i]);
      size[now] += size[toit[i]];
    }
}
inline void subdivide(int now, int tp) {
  top[redfn[L[now] = ++timestamp] = now] = tp;
  int heavy = 0;
  for (int i = side[now]; i; i = nxt[i])
    if (toit[i] != father[now] && size[toit[i]] > size[heavy]) heavy = toit[i];
  if (heavy) {
    subdivide(heavy, tp);
    for (int i = side[now]; i; i = nxt[i])
      if (toit[i] != father[now] && toit[i] != heavy)
        subdivide(toit[i], toit[i]);
  }
  R[now] = timestamp;
}
inline void build(int now, int l, int r) {
  if (l == r) {
    if (people[redfn[l]].empty())
      tree[now] = Node(inf, 0, 0);
    else
      tree[now] =
          Node(people[redfn[l]].back(), redfn[l], people[redfn[l]].back());
    return;
  }
  int mid = (l + r) >> 1;
  build(now << 1, l, mid);
  build(now << 1 | 1, mid + 1, r);
  tree[now] = tree[now << 1] + tree[now << 1 | 1];
}
inline void pushdown(int now, int l, int r) {
  if (l != r) {
    tree[now << 1].key1 += tag[now];
    tag[now << 1] += tag[now];
    tree[now << 1 | 1].key1 += tag[now];
    tag[now << 1 | 1] += tag[now];
  }
  tag[now] = 0;
}
inline void increase(int now, int l, int r, int ql, int qr, long long inc) {
  if (tag[now]) pushdown(now, l, r);
  if (!tree[now].id) return;
  if (l == ql && r == qr) {
    tree[now].key1 += inc;
    tag[now] += inc;
    return;
  }
  int mid = (l + r) >> 1;
  if (qr <= mid)
    increase(now << 1, l, mid, ql, qr, inc);
  else if (ql > mid)
    increase(now << 1 | 1, mid + 1, r, ql, qr, inc);
  else
    increase(now << 1, l, mid, ql, mid, inc),
        increase(now << 1 | 1, mid + 1, r, mid + 1, qr, inc);
  tree[now] = tree[now << 1] + tree[now << 1 | 1];
}
inline Node query(int now, int l, int r, int ql, int qr) {
  if (tag[now]) pushdown(now, l, r);
  if (!tree[now].id) return tree[now];
  if (l == ql && r == qr) return tree[now];
  int mid = (l + r) >> 1;
  if (qr <= mid)
    return query(now << 1, l, mid, ql, qr);
  else if (ql > mid)
    return query(now << 1 | 1, mid + 1, r, ql, qr);
  else
    return query(now << 1, l, mid, ql, mid) +
           query(now << 1 | 1, mid + 1, r, mid + 1, qr);
}
inline void erase(int now, int l, int r, int pos) {
  if (tag[now]) pushdown(now, l, r);
  if (l == r) {
    tree[now].key1 -= (long long)people[redfn[l]].back();
    people[redfn[l]].pop_back();
    if (people[redfn[l]].empty())
      tree[now] = Node(inf, 0, 0);
    else {
      tree[now].key1 += (long long)people[redfn[l]].back();
      tree[now].id = people[redfn[l]].back();
    }
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    erase(now << 1, l, mid, pos);
  else
    erase(now << 1 | 1, mid + 1, r, pos);
  tree[now] = tree[now << 1] + tree[now << 1 | 1];
}
inline Node query(int a, int b) {
  auto ret = Node(inf, 0, 0);
  while (top[a] != top[b]) {
    if (dep[top[a]] < dep[top[b]]) swap(a, b);
    if (!flag[a]) {
      auto res = query(1, 1, N, L[top[a]], L[a]);
      if (!res.id)
        flag[a] = true;
      else
        ret = ret + res;
    }
    a = father[top[a]];
  }
  if (dep[a] < dep[b]) swap(a, b);
  ret = ret + query(1, 1, N, L[b], L[a]);
  return ret;
}
int main() {
  N = gi(), M = gi(), Q = gi();
  for (int i = 1; i < N; ++i) ins(gi(), gi());
  for (int i = 1; i <= M; ++i) people[gi()].push_back(i);
  for (int i = 1; i <= N; ++i) reverse(people[i].begin(), people[i].end());
  dfs(1);
  subdivide(1, 1);
  build(1, 1, N);
  while (Q--) {
    if (gi() == 1) {
      vector<int> vec;
      int u = gi(), v = gi(), k = gi();
      while (k--) {
        auto res = query(v, u);
        if (!res.id) break;
        vec.push_back(res.id);
        erase(1, 1, N, L[res.key2]);
      }
      printf("%d", (int)vec.size());
      for (auto x : vec) printf(" %d", x);
      putchar('\n');
    } else {
      int u = gi(), k = gi();
      increase(1, 1, N, L[u], R[u], k);
    }
  }
  return 0;
}
