#include <bits/stdc++.h>
using namespace std;
const long long INF = (long long)2e14;
int n, m, q, t = 0, cnt, ts = 1;
vector<vector<int>> g;
vector<vector<long long>> weight;
vector<int> tin, tout, d, anc, top, heavy, subtree_size;
vector<int> query_list, chain, girl_pos, order;
vector<pair<int, int>> pos;
struct girl {
  long long w, psh;
  int i, cross;
  girl(long long _w = INF, int _i = 0, int _cross = 0) {
    w = _w;
    psh = 0;
    cross = _cross;
    i = _i;
  }
  bool operator<(const girl &x) const {
    return w < x.w || w == x.w && cross < x.cross;
  }
};
vector<girl> st;
void dfs(int v) {
  subtree_size[v] = 1;
  for (auto u : g[v]) {
    if (u != anc[v]) {
      d[u] = d[v] + 1;
      anc[u] = v;
      dfs(u);
      subtree_size[v] += subtree_size[u];
      if (heavy[v] == -1 || subtree_size[u] > subtree_size[heavy[v]])
        heavy[v] = u;
    }
  }
}
void dfs_hld(int v) {
  tin[v] = ++t;
  order.push_back(v);
  if (heavy[v] != -1) {
    dfs_hld(heavy[v]);
    chain[v] = chain[heavy[v]];
    top[chain[v]] = v;
  } else {
    chain[v] = cnt++;
    top.push_back(v);
  }
  for (auto u : g[v])
    if (u != heavy[v] && u != anc[v]) dfs_hld(u);
  tout[v] = ++t;
}
void build_tree() {
  int sz = 0;
  for (int i = 0; i < n; i++) {
    if (weight[i].empty()) weight[i].push_back(INF);
    sz += weight[i].size();
  }
  while (ts < sz) ts <<= 1;
  st.resize(2 * ts);
  sz = 0;
  for (int i = 0; i < n; i++) {
    int v = order[i];
    for (int j = 0; j < weight[v].size(); j++) {
      st[ts + sz++] = girl(weight[v][j], weight[v][j], v);
      if (weight[v][j] != INF) girl_pos[weight[v][j]] = sz;
    }
    if (weight[v][0] != INF) {
      pos[v].first = girl_pos[weight[v][0]];
      pos[v].second = girl_pos[weight[v].back()];
    } else
      pos[v].first = pos[v].second = sz;
  }
  for (int i = ts - 1; i >= 1; i--) st[i] = min(st[2 * i], st[2 * i + 1]);
}
void hld(int v) {
  tin.resize(n);
  tout.resize(n);
  d.resize(n);
  subtree_size.resize(n);
  heavy.resize(n, -1);
  anc.resize(n);
  chain.resize(n);
  pos.resize(n);
  anc[v] = -1;
  dfs(v);
  dfs_hld(v);
  build_tree();
}
void push(int v) {
  if (st[v].psh) {
    st[v].w += st[v].psh;
    if (v < ts) {
      st[2 * v].psh += st[v].psh;
      st[2 * v + 1].psh += st[v].psh;
    }
    st[v].psh = 0;
  }
}
void change_segment(int l, int r, int L, int R, long long dt, int v = 1) {
  push(v);
  if (l <= L && R <= r) {
    st[v].psh += dt;
    push(v);
    return;
  }
  if (l > R || r < L) return;
  change_segment(l, r, L, (L + R) / 2, dt, 2 * v);
  change_segment(l, r, (L + R) / 2 + 1, R, dt, 2 * v + 1);
  st[v] = min(st[2 * v], st[2 * v + 1]);
}
girl get_min(int l, int r, int L, int R, int v = 1) {
  push(v);
  if (l <= L && R <= r) return st[v];
  if (l > R || L > r) return girl();
  return min(get_min(l, r, L, (L + R) / 2, 2 * v),
             get_min(l, r, (L + R) / 2 + 1, R, 2 * v + 1));
}
void step_back(int i) {
  if (i > 1) step_back(i / 2);
  push(i);
}
void change_element(int i, long long val) {
  st[i + ts - 1].w = val;
  st[i + ts - 1].psh = 0;
  step_back((i + ts - 1) / 2);
  for (i = (i + ts - 1) / 2; i >= 1; i >>= 1) {
    push(2 * i);
    push(2 * i + 1);
    st[i] = min(st[2 * i], st[2 * i + 1]);
  }
}
int least_common_ancestor(int v, int u) {
  while (chain[v] != chain[u]) {
    if (d[top[chain[v]]] > d[top[chain[u]]])
      v = anc[top[chain[v]]];
    else
      u = anc[top[chain[u]]];
  }
  return d[v] < d[u] ? v : u;
}
void query(int v, int u, int k) {
  int lca = least_common_ancestor(v, u), tmp_v, tmp_u;
  while (k--) {
    tmp_v = v;
    tmp_u = u;
    girl tmp;
    while (chain[tmp_v] != chain[lca]) {
      tmp = min(
          tmp, get_min(pos[top[chain[tmp_v]]].first, pos[tmp_v].second, 1, ts));
      tmp_v = anc[top[chain[tmp_v]]];
    }
    tmp = min(tmp, get_min(pos[lca].first, pos[tmp_v].second, 1, ts));
    while (chain[tmp_u] != chain[lca]) {
      tmp = min(
          tmp, get_min(pos[top[chain[tmp_u]]].first, pos[tmp_u].second, 1, ts));
      tmp_u = anc[top[chain[tmp_u]]];
    }
    tmp = min(tmp, get_min(pos[lca].first, pos[tmp_u].second, 1, ts));
    if (tmp.w >= INF)
      break;
    else {
      query_list.push_back(tmp.i);
      change_segment(girl_pos[tmp.i], girl_pos[tmp.i], 1, ts, INF);
    }
  }
  cout << query_list.size() << ' ';
  for (auto x : query_list) cout << x + 1 << ' ';
  cout << '\n';
  query_list.clear();
}
void change_subtree(int i, int k) {
  int l = -1, r = n - 1;
  while (r - l > 1) {
    int m = (l + r) / 2;
    if (tin[order[m]] < tin[i])
      l = m;
    else
      r = m;
  }
  int L = 0, R = n;
  while (R - L > 1) {
    int M = (L + R) / 2;
    if (tin[order[M]] > tout[i])
      R = M;
    else
      L = M;
  }
  change_segment(pos[order[r]].first, pos[order[L]].second, 1, ts, k);
}
int main() {
  ios::sync_with_stdio(false);
  cin >> n >> m >> q;
  g.resize(n);
  for (int i = 0, v, u; i < n - 1; i++) {
    cin >> u >> v;
    g[u - 1].push_back(v - 1);
    g[v - 1].push_back(u - 1);
  }
  weight.resize(n);
  girl_pos.resize(m);
  for (int i = 0, v; i < m; i++) {
    cin >> v;
    weight[v - 1].push_back(i);
  }
  hld(0);
  while (q--) {
    int t, i, j, k;
    cin >> t;
    if (t == 1) {
      cin >> i >> j >> k;
      if (k > n) k -= k / n * n;
      query(i - 1, j - 1, k);
    } else {
      cin >> i >> k;
      change_subtree(i - 1, k);
    }
  }
  return 0;
}
