#include <bits/stdc++.h>
using namespace std;
inline long long getint() {
  long long _x = 0, _tmp = 1;
  char _tc = getchar();
  while ((_tc < '0' || _tc > '9') && _tc != '-') _tc = getchar();
  if (_tc == '-') _tc = getchar(), _tmp = -1;
  while (_tc >= '0' && _tc <= '9') _x *= 10, _x += (_tc - '0'), _tc = getchar();
  return _x * _tmp;
}
inline long long add(long long _x, long long _y,
                     long long _mod = 1000000007ll) {
  long long _ = _x + _y;
  if (_ >= _mod) _ -= _mod;
  return _;
}
inline long long sub(long long _x, long long _y,
                     long long _mod = 1000000007ll) {
  long long _ = _x - _y;
  if (_ < 0) _ += _mod;
  return _;
}
inline long long mul(long long _x, long long _y,
                     long long _mod = 1000000007ll) {
  long long _ = _x * _y;
  if (_ >= _mod) _ %= _mod;
  return _;
}
long long mypow(long long _a, long long _x, long long _mod) {
  if (_x == 0) return 1ll;
  long long _tmp = mypow(_a, _x / 2, _mod);
  _tmp = mul(_tmp, _tmp, _mod);
  if (_x & 1) _tmp = mul(_tmp, _a, _mod);
  return _tmp;
}
long long mymul(long long _a, long long _x, long long _mod) {
  if (_x == 0) return 0ll;
  long long _tmp = mymul(_a, _x / 2, _mod);
  _tmp = add(_tmp, _tmp, _mod);
  if (_x & 1) _tmp = add(_tmp, _a, _mod);
  return _tmp;
}
inline bool equal(double _x, double _y) {
  return _x > _y - 1e-9 && _x < _y + 1e-9;
}
int __ = 1, _cs;
const int LOG = 19;
struct HLD {
  int n;
  vector<int> g[101010];
  int sz[101010], dep[101010];
  int ts, tid[101010], tdi[101010], tl[101010], tr[101010];
  int mom[101010][LOG], head[101010];
  void dfssz(int u, int p) {
    dep[u] = dep[p] + 1;
    mom[u][0] = p;
    sz[u] = 1;
    head[u] = u;
    for (int& v : g[u])
      if (v != p) {
        dep[v] = dep[u] + 1;
        dfssz(v, u);
        sz[u] += sz[v];
      }
  }
  void dfshl(int u) {
    ts++;
    tid[u] = tl[u] = tr[u] = ts;
    tdi[tid[u]] = u;
    sort((g[u]).begin(), (g[u]).end(),
         [&](int a, int b) { return sz[a] > sz[b]; });
    bool flag = 1;
    for (int& v : g[u])
      if (v != mom[u][0]) {
        if (flag) head[v] = head[u], flag = 0;
        dfshl(v);
        tr[u] = tr[v];
      }
  }
  inline int lca(int a, int b) {
    if (dep[a] > dep[b]) swap(a, b);
    int diff = dep[b] - dep[a];
    for (int k = (LOG - 1); k >= (0); k--)
      if (diff & (1 << k)) {
        b = mom[b][k];
      }
    if (a == b) return a;
    for (int k = (LOG - 1); k >= (0); k--)
      if (mom[a][k] != mom[b][k]) {
        a = mom[a][k];
        b = mom[b][k];
      }
    return mom[a][0];
  }
  void init(int _n) {
    n = _n;
    for (int i = (1); i <= (n); i++) g[i].clear();
  }
  void addEdge(int u, int v) {
    g[u].push_back(v);
    g[v].push_back(u);
  }
  void yutruli() {
    dfssz(1, 0);
    ts = 0;
    dfshl(1);
    for (int k = (1); k <= (LOG - 1); k++)
      for (int i = (1); i <= (n); i++) mom[i][k] = mom[mom[i][k - 1]][k - 1];
  }
  vector<tuple<int, int> > getPath(int u, int v) {
    vector<tuple<int, int> > res;
    while (tid[u] < tid[head[v]]) {
      res.push_back(tuple<int, int>(tid[head[v]], tid[v]));
      v = mom[head[v]][0];
    }
    res.push_back(tuple<int, int>(tid[u], tid[v]));
    reverse((res).begin(), (res).end());
    return res;
  }
} tree;
void build() {}
queue<int> tmp[101010];
long long tag[101010 << 2];
pair<long long, long long> st[101010 << 2];
void build_st(int no, int l, int r) {
  if (l == r) {
    if (tmp[l].empty())
      st[no] = {10000000000000000ll, 10000000000000000ll};
    else
      st[no] = {tmp[l].front(), tree.tdi[l]};
    return;
  }
  build_st((no << 1), l, ((l + r) >> 1));
  build_st((1 + (no << 1)), ((l + r) >> 1) + 1, r);
  st[no] = min(st[(no << 1)], st[(1 + (no << 1))]);
}
inline void push(int no, int l, int r) {
  if (tag[no]) {
    tag[(no << 1)] += tag[no];
    st[(no << 1)].first += tag[no];
    tag[(1 + (no << 1))] += tag[no];
    st[(1 + (no << 1))].first += tag[no];
  }
  tag[no] = 0;
}
pair<long long, long long> query(int no, int l, int r, int ql, int qr) {
  if (r < ql || l > qr || ql > qr)
    return {10000000000000000ll, 10000000000000000ll};
  if (ql <= l && r <= qr) return st[no];
  push(no, l, r);
  return min(query((no << 1), l, ((l + r) >> 1), ql, qr),
             query((1 + (no << 1)), ((l + r) >> 1) + 1, r, ql, qr));
}
void Add(int no, int l, int r, int ql, int qr, long long dlt) {
  if (r < ql || l > qr || ql > qr) return;
  if (ql <= l && r <= qr) {
    tag[no] += dlt;
    st[no].first += dlt;
    return;
  }
  push(no, l, r);
  Add((no << 1), l, ((l + r) >> 1), ql, qr, dlt);
  Add((1 + (no << 1)), ((l + r) >> 1) + 1, r, ql, qr, dlt);
  st[no] = min(st[(no << 1)], st[(1 + (no << 1))]);
}
void Del(int no, int l, int r, int p) {
  if (l == r) {
    assert(!tmp[l].empty());
    tmp[l].pop();
    if (tmp[l].empty())
      st[no] = {10000000000000000ll, 10000000000000000ll};
    else
      st[no] = {tmp[l].front() + tag[no], tree.tdi[l]};
    return;
  }
  push(no, l, r);
  if (p <= ((l + r) >> 1))
    Del((no << 1), l, ((l + r) >> 1), p);
  else
    Del((1 + (no << 1)), ((l + r) >> 1) + 1, r, p);
  st[no] = min(st[(no << 1)], st[(1 + (no << 1))]);
}
int n, m, q;
void init() {
  n = getint();
  m = getint();
  q = getint();
  tree.init(n);
  for (int i = 1; i < n; i++) {
    int u = getint();
    int v = getint();
    tree.addEdge(u, v);
  }
  tree.yutruli();
  for (int i = 1; i <= m; i++) tmp[tree.tid[getint()]].push(i);
  build_st(1, 1, n);
}
void solve() {
  while (q--) {
    int cmd = getint();
    if (cmd == 1) {
      int v = getint();
      int u = getint();
      int k = getint();
      int lca = tree.lca(v, u);
      vector<tuple<int, int> > p1 = tree.getPath(lca, u);
      vector<tuple<int, int> > p2 = tree.getPath(lca, v);
      priority_queue<
          pair<pair<long long, long long>, tuple<int, int> >,
          vector<pair<pair<long long, long long>, tuple<int, int> > >,
          greater<pair<pair<long long, long long>, tuple<int, int> > > >
          heap;
      for (tuple<int, int> tp : p1) {
        pair<long long, long long> xp = query(1, 1, n, get<0>(tp), get<1>(tp));
        if (xp.second != 10000000000000000ll) heap.push({xp, tp});
      }
      for (tuple<int, int> tp : p2) {
        pair<long long, long long> xp = query(1, 1, n, get<0>(tp), get<1>(tp));
        if (xp.second != 10000000000000000ll) heap.push({xp, tp});
      }
      vector<int> ans;
      int got = 0;
      while (heap.size() && got < k) {
        pair<pair<long long, long long>, tuple<int, int> > xp = heap.top();
        heap.pop();
        pair<long long, long long> ap = xp.first;
        tuple<int, int> tp = xp.second;
        pair<long long, long long> cp = query(1, 1, n, get<0>(tp), get<1>(tp));
        if (cp != ap) {
          if (cp.second != 10000000000000000ll) heap.push({cp, tp});
          continue;
        }
        got++;
        ans.push_back(tmp[tree.tid[ap.second]].front());
        Del(1, 1, n, tree.tid[ap.second]);
        ap = query(1, 1, n, get<0>(tp), get<1>(tp));
        if (ap.second != 10000000000000000ll) heap.push({ap, tp});
      }
      if (ans.empty())
        puts("0");
      else {
        printf("%d ", (int)ans.size());
        for (size_t i = 0; i < ans.size(); i++)
          printf("%d%c", ans[i], " \n"[i + 1 == ans.size()]);
      }
    } else {
      int v = getint();
      int k = getint();
      Add(1, 1, n, tree.tl[v], tree.tr[v], k);
    }
  }
}
int main() {
  build();
  while (__--) {
    init();
    solve();
  }
}
