#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const int LN = 21;
const long long MIN = 1e15;
inline pair<long long, int> maxPair(pair<long long, int> prior1,
                                    pair<long long, int> prior2) {
  if (prior1.first <= prior2.first && prior1.second > 0) return prior1;
  return prior2;
}
struct node {
  node *left, *right;
  pair<long long, int> val1, val2;
  long long lazy;
  node* build(int start, int end) {
    val1.first = MIN, val1.second = 0, val2.first = MIN, val2.second = 0,
    lazy = 0;
    if (start != end) {
      int mid = (start + end) / 2;
      left = new node;
      right = new node;
      left = left->build(start, mid), right = right->build(mid + 1, end);
    }
    return this;
  }
  inline void merge() {
    val1 = maxPair(left->val1, right->val1),
    val2 = maxPair(right->val2, left->val2);
    val1.first += lazy, val2.first += lazy;
  }
  node* add(int start, int end, int a, int b, long long v) {
    if (start >= a && end <= b) {
      lazy += v;
      val1.first += v;
      val2.first += v;
    } else if (start > b || end < a)
      return this;
    else {
      int mid = (start + end) / 2;
      left = left->add(start, mid, a, b, v),
      right = right->add(mid + 1, end, a, b, v);
      merge();
    }
    return this;
  }
  node* setVal(int start, int end, int x, pair<long long, int> v) {
    int mid = (start + end) / 2;
    if (start == end) {
      v.first += lazy;
      val1 = v, val2 = v;
      return this;
    } else if (x <= mid) {
      left = left->setVal(start, mid, x, v);
    } else {
      right = right->setVal(mid + 1, end, x, v);
    }
    merge();
    return this;
  }
  pair<long long, int> query1(int start, int end, int a, int b) {
    if (b < a) cout << "WTF" << endl;
    if (start >= a && end <= b) {
      return val1;
    } else if (start > b || end < a)
      return make_pair(MIN, 0);
    else {
      int mid = (start + end) / 2;
      pair<long long, int> temp = maxPair(left->query1(start, mid, a, b),
                                          right->query1(mid + 1, end, a, b));
      temp.first += lazy;
      return temp;
    }
  }
  pair<long long, int> query2(int start, int end, int a, int b) {
    if (b < a) cout << "WTF" << endl;
    if (start >= a && end <= b) {
      return val2;
    } else if (start > b || end < a)
      return make_pair(MIN, 0);
    else {
      int mid = (start + end) / 2;
      pair<long long, int> temp = maxPair(right->query2(mid + 1, end, a, b),
                                          left->query2(start, mid, a, b));
      temp.first += lazy;
      return temp;
    }
  }
};
vector<int> ans;
int n;
int C[N];
queue<int> girls[N];
vector<int> adj[N];
int dp[N][LN];
int Log2[N];
int depth[N];
int subtree[N];
long long bit[N];
int arrival[N], departure[N];
pair<int, int> maxSubtree[N];
int Chains = 0, hldIndex = 0;
int headOfChain[N];
int chainNumofV[N];
int chainSize[N];
int indexChain[N];
int lastInChain[N];
node* root = NULL;
int timer = 0;
void add(int i, long long v) {
  while (i <= n) {
    bit[i] += v;
    i += (i & -i);
  }
}
long long sum(int i) {
  long long ans = 0;
  while (i > 0) {
    ans += bit[i];
    i -= (i & -i);
  }
  return ans;
}
void dfs(int v, int p) {
  arrival[v] = ++timer;
  depth[v] = 1 + depth[p];
  subtree[v] = 1;
  maxSubtree[v].first = 0, maxSubtree[v].second = 0;
  dp[v][0] = p;
  for (int i = 1; i <= Log2[depth[v]]; i++) {
    dp[v][i] = dp[dp[v][i - 1]][i - 1];
  }
  for (auto c : adj[v]) {
    if (c != p) {
      dfs(c, v);
      subtree[v] += subtree[c];
      if (subtree[c] > maxSubtree[v].first)
        maxSubtree[v].first = subtree[c], maxSubtree[v].second = c;
    }
  }
  departure[v] = timer;
}
void dfsHld(int v, int p) {
  ++hldIndex;
  if (headOfChain[Chains] == 0) headOfChain[Chains] = v;
  chainSize[Chains]++;
  indexChain[v] = hldIndex;
  chainNumofV[v] = Chains;
  lastInChain[Chains] = v;
  if (maxSubtree[v].first != 0) {
    dfsHld(maxSubtree[v].second, v);
  }
  for (auto c : adj[v]) {
    if (c != p && c != maxSubtree[v].second) {
      Chains++;
      dfsHld(c, v);
    }
  }
}
int lca(int a, int b) {
  if (depth[a] > depth[b]) swap(a, b);
  for (int i = Log2[depth[b]]; i >= 0; i--) {
    if (depth[b] - (1 << i) >= depth[a]) b = dp[b][i];
  }
  if (a != b) {
    for (int i = Log2[depth[a]]; i >= 0; i--) {
      if (dp[a][i] != dp[b][i]) a = dp[a][i], b = dp[b][i];
    }
    a = dp[a][0];
  }
  return a;
}
void subtreeIncrease(int v, long long k) {
  int ch = chainNumofV[v];
  if (headOfChain[ch] != v) {
    root = root->add(1, n, indexChain[v], indexChain[lastInChain[ch]], k);
  }
  add(arrival[v], k);
  add(departure[v] + 1, -1 * k);
}
void putNextGirl(int i) {
  int x;
  if (!girls[i].empty()) {
    x = girls[i].front();
    girls[i].pop();
    root = root->setVal(1, n, indexChain[i], make_pair(x, x));
  } else {
    root = root->setVal(1, n, indexChain[i], make_pair(MIN, 0));
  }
}
inline void initSetup() {
  root = new node;
  root = root->build(1, n);
  for (int i = 1; i <= n; i++) {
    putNextGirl(i);
  }
}
pair<long long, int> bottomToUp(int v, int l) {
  pair<long long, int> t = make_pair(MIN, 0), temp;
  int ch = chainNumofV[v];
  int ch2 = chainNumofV[l];
  while (ch != ch2) {
    temp = root->query2(1, n, indexChain[headOfChain[ch]], indexChain[v]);
    temp.first += sum(arrival[headOfChain[ch]]);
    t = maxPair(t, temp);
    v = dp[headOfChain[ch]][0];
    ch = chainNumofV[v];
  }
  temp = root->query2(1, n, indexChain[l], indexChain[v]);
  temp.first += sum(arrival[headOfChain[ch]]);
  t = maxPair(t, temp);
  return t;
}
pair<long long, int> upToBottom(int v, int l) {
  pair<long long, int> t = make_pair(MIN, 0), temp;
  int ch = chainNumofV[v];
  int ch2 = chainNumofV[l];
  while (ch != ch2) {
    temp = root->query1(1, n, indexChain[headOfChain[ch]], indexChain[v]);
    temp.first += sum(arrival[headOfChain[ch]]);
    t = maxPair(temp, t);
    v = dp[headOfChain[ch]][0];
    ch = chainNumofV[v];
  }
  temp = root->query1(1, n, indexChain[l], indexChain[v]);
  temp.first += sum(arrival[headOfChain[ch]]);
  t = maxPair(temp, t);
  return t;
}
inline void processQuery(int v, int u, int k) {
  ans.clear();
  int lc = lca(v, u);
  pair<long long, int> t1, t2, g;
  while (k--) {
    t1 = bottomToUp(v, lc);
    t2 = upToBottom(u, lc);
    g = maxPair(t1, t2);
    if (g.second <= 0) break;
    ans.push_back(g.second);
    putNextGirl(C[g.second]);
  }
}
int main() {
  int m, q, u, v, t, k;
  scanf("%d %d %d", &n, &m, &q);
  Log2[0] = -1;
  for (int i = 1; i < n; i++) {
    scanf("%d %d", &u, &v);
    adj[u].push_back(v);
    adj[v].push_back(u);
    Log2[i] = Log2[i - 1];
    if ((i & -i) == i) {
      Log2[i]++;
    }
  }
  Log2[n] = Log2[n - 1];
  if ((n & -n) == n) {
    Log2[n]++;
  }
  for (int i = 1; i <= m; i++) {
    scanf("%d", C + i);
    girls[C[i]].push(i);
  }
  depth[0] = -1;
  dfs(1, 0);
  Chains++;
  dfsHld(1, 0);
  initSetup();
  assert(hldIndex == n);
  while (q--) {
    scanf("%d", &t);
    if (t == 1) {
      scanf("%d %d %d", &v, &u, &k);
      processQuery(v, u, k);
      cout << ans.size() << " ";
      for (auto c : ans) cout << c << " ";
      cout << endl;
    } else {
      scanf("%d %d", &v, &k);
      subtreeIncrease(v, k);
    }
  }
  return 0;
}
