#include <bits/stdc++.h>
using namespace std;
template <typename T>
T nextInt() {
  T x = 0, p = 1;
  char ch;
  do {
    ch = getchar();
  } while (ch <= ' ');
  if (ch == '-') {
    p = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10 + (ch - '0');
    ch = getchar();
  }
  return x * p;
}
const int maxN = 1e5 + 10;
const int maxL = 17;
const int mod = (int)1e9 + 7;
const long long LLINF = (long long)1e18 + 5;
const pair<long long, int> INF = make_pair(LLINF, -1);
struct segmentTree {
  int n;
  pair<long long, int>* t;
  long long* p;
  segmentTree() {}
  segmentTree(int n) : n(n) {
    t = new pair<long long, int>[4 * n];
    p = new long long[4 * n];
    fill(t, t + 4 * n, INF);
    fill(p, p + 4 * n, 0);
  }
  void add(int v, long long x) {
    p[v] += x;
    t[v].first += x;
  }
  void push(int v) {
    if (p[v] == 0) return;
    add(v + v, p[v]);
    add(v + v + 1, p[v]);
    p[v] = 0;
  }
  void addOnInterval(int l, int r, int x) {
    addOnInterval(1, l, r, x, 0, n - 1);
  }
  void addOnInterval(int v, int l, int r, int x, int tl, int tr) {
    if (l <= tl && tr <= r) {
      add(v, x);
      return;
    }
    push(v);
    int tm = (tl + tr) / 2;
    if (l <= tm) {
      addOnInterval(v + v, l, r, x, tl, tm);
    }
    if (r > tm) {
      addOnInterval(v + v + 1, l, r, x, tm + 1, tr);
    }
    t[v] = min(t[v + v], t[v + v + 1]);
  }
  pair<long long, int> getMinOnSuffix(int l) { return getMin(l, n - 1); }
  pair<long long, int> getMin(int l, int r) {
    if (l > r) return INF;
    return getMin(1, l, r, 0, n - 1);
  }
  pair<long long, int> getMin(int v, int l, int r, int tl, int tr) {
    if (l <= tl && tr <= r) {
      return t[v];
    }
    push(v);
    int tm = (tl + tr) / 2;
    if (r <= tm) {
      return getMin(v + v, l, r, tl, tm);
    }
    if (l > tm) {
      return getMin(v + v + 1, l, r, tm + 1, tr);
    }
    return min(getMin(v + v, l, r, tl, tm),
               getMin(v + v + 1, l, r, tm + 1, tr));
  }
  void update(int idx, pair<long long, int> x) { update(1, idx, x, 0, n - 1); }
  void update(int v, int idx, pair<long long, int> x, int tl, int tr) {
    if (tl == tr) {
      t[v] = x;
      t[v].first += p[v];
      return;
    }
    push(v);
    int tm = (tl + tr) / 2;
    if (idx <= tm) {
      update(v + v, idx, x, tl, tm);
    } else {
      update(v + v + 1, idx, x, tm + 1, tr);
    }
    t[v] = min(t[v + v], t[v + v + 1]);
  }
};
int n, m, q;
vector<int> g[maxN];
int timer;
int up[maxN][maxL];
int sz[maxN];
int l[maxN];
int r[maxN];
void dfs(int v, int par = 0) {
  l[v] = timer++;
  sz[v] = 1;
  up[v][0] = par;
  for (int i = 1; i < maxL; ++i) {
    up[v][i] = up[up[v][i - 1]][i - 1];
  }
  for (int x : g[v]) {
    if (x == par) continue;
    dfs(x, v);
    sz[v] += sz[x];
  }
  r[v] = l[v] + sz[v] - 1;
}
bool isAncestor(int x, int y) { return l[x] <= l[y] && r[y] <= r[x]; }
int lca(int x, int y) {
  if (isAncestor(x, y)) return x;
  if (isAncestor(y, x)) return y;
  for (int i = maxL - 1; i >= 0; --i) {
    if (up[x][i] != 0 && !isAncestor(up[x][i], y)) {
      x = up[x][i];
    }
  }
  return up[x][0];
}
vector<int> girls[maxN];
int girlIter[maxN];
int nodes[maxN];
int listSz = 0;
int highest[maxN];
int pathNum[maxN];
int posPath[maxN];
segmentTree t[maxN];
int curPath = 0;
void processPath() {
  curPath++;
  highest[curPath] = nodes[0];
  t[curPath] = segmentTree(listSz);
  for (int i = 0; i < listSz; ++i) {
    int v = nodes[i];
    pathNum[v] = curPath;
    posPath[v] = listSz - 1 - i;
    if (!girls[v].empty()) {
      int girl = girls[v][0];
      girlIter[v]++;
      t[curPath].update(posPath[v], make_pair(girl, v));
    }
  }
  listSz = 0;
}
void build(int v, int par = -1) {
  nodes[listSz++] = v;
  int heavySon = -1;
  for (int x : g[v]) {
    if (x == par) continue;
    if (2 * sz[x] >= sz[v]) {
      heavySon = x;
    }
  }
  if (heavySon == -1) {
    processPath();
  } else {
    build(heavySon, v);
  }
  for (int x : g[v]) {
    if (x == par || x == heavySon) continue;
    build(x, v);
  }
}
long long fw[maxN];
void addFw(int x, int k) {
  for (; x <= n; x |= x + 1) {
    fw[x] += k;
  }
}
long long getFw(int x) {
  long long ret = 0;
  for (; x >= 0; x = (x & (x + 1)) - 1) {
    ret += fw[x];
  }
  return ret;
}
void addInSubtree(int v, int k) {
  addFw(l[v], k);
  addFw(r[v] + 1, -k);
  int a = pathNum[v];
  int b = posPath[v];
  t[a].addOnInterval(0, b, k);
}
int result[maxN];
int resultSz = 0;
pair<long long, int> query(int x, int y) {
  int a = pathNum[x];
  int b = posPath[x];
  int c = pathNum[y];
  int d = posPath[y];
  int z38 = up[highest[a]][0];
  long long extra = (z38 == 0 ? 0 : getFw(l[z38]));
  pair<long long, int> ret = INF;
  if (a == c) {
    ret = t[a].getMin(b, d);
    ret.first += extra;
  } else {
    ret = t[a].getMinOnSuffix(b);
    ret.first += extra;
    ret = min(ret, query(z38, y));
  }
  return ret;
}
bool process(int x, int y) {
  int z = lca(x, y);
  pair<long long, int> ret = min(query(x, z), query(y, z));
  if (ret.second == -1) return false;
  int v = ret.second;
  int girl = girls[v][girlIter[v] - 1];
  result[resultSz++] = girl;
  int a = pathNum[v];
  int b = posPath[v];
  if (girlIter[v] != (int)girls[v].size()) {
    t[a].update(b, make_pair(girls[v][girlIter[v]++], v));
  } else {
    t[a].update(b, make_pair(LLINF, -1));
  }
  return true;
}
int main() {
  n = nextInt<int>();
  m = nextInt<int>();
  q = nextInt<int>();
  for (int i = 0; i < n - 1; ++i) {
    int x = nextInt<int>();
    int y = nextInt<int>();
    g[x].push_back(y);
    g[y].push_back(x);
  }
  for (int i = 1; i <= m; ++i) {
    int c = nextInt<int>();
    girls[c].push_back(i);
  }
  dfs(1);
  build(1);
  while (q--) {
    int type = nextInt<int>();
    if (type == 1) {
      int v, u, k;
      v = nextInt<int>();
      u = nextInt<int>();
      k = nextInt<int>();
      resultSz = 0;
      while (k-- && process(v, u))
        ;
      printf("%d", resultSz);
      for (int i = 0; i < resultSz; ++i) {
        printf(" %d", result[i]);
      }
      putchar('\n');
    } else {
      int v, k;
      v = nextInt<int>();
      k = nextInt<int>();
      addInSubtree(v, k);
    }
  }
  return 0;
}
