9 5 14
7 1 4 8 5 2 6 9 3
2 8
1 6
5 7
1 3
3 9
1 5
1 8
1 5
1 4
1 8
1 3
1 5
1 5
1 7
1 7
2 3
1 2
1 1
1 2
 6 5 8
1 2 6 3 4 5
2 4
1 3
1 6
3 5
2 5
1 1
1 4
1 1
2 1
2 5
2 2
2 3
1 4
 2 1 3
1 2
1 2
1 1
1 1
1 1

6
9
5
8
1
7
0
0
0
0
0
4
0
 6
5
4
3
 2
1
0

#include <bits/stdc++.h>
const int maxn = 5e5 + 1;
const int maxm = 3e5 + 1;
const int maxq = 5e5 + 1;
inline void read(int &x) {
  x = 0;
  int f = 1;
  char s = getchar();
  while (s < '0' || s > '9') {
    if (s == '-') f = -1;
    s = getchar();
  }
  while (s >= '0' && s <= '9') {
    x = (x << 1) + (x << 3) + (s & 15);
    s = getchar();
  }
  x *= f;
}
int p[maxn], n, m, q, opt[maxq], x[maxq], bcj[maxn << 1], idx, used[maxm],
    ch[maxm], cnt, fa[maxn << 1][19], siz[maxn << 1], tag[maxn << 1],
    dep[maxn << 1];
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
inline int find(int x) { return (bcj[x] == x) ? x : bcj[x] = find(bcj[x]); }
struct edge {
  int u, v, t, idx;
} E[maxm];
inline bool cmp(edge a, edge b) { return a.t > b.t; }
struct Edge {
  int u, v;
} e[maxn << 2];
int head[maxn << 1], ecnt;
inline void addedge(int u, int v) {
  e[++ecnt].v = v;
  e[ecnt].u = head[u];
  head[u] = ecnt;
}
inline void add(int u, int v) { addedge(u, v); }
struct Segment_Tree {
  int val[maxn << 3];
  inline void pushup(int rt) { val[rt] = max(val[rt << 1], val[rt << 1 | 1]); }
  inline void insert(int rt, int l, int r, int k, int ch) {
    if (l == r) return (void)(val[rt] = ch);
    if (k <= ((l + r) >> 1))
      insert(rt << 1, l, ((l + r) >> 1), k, ch);
    else
      insert(rt << 1 | 1, ((l + r) >> 1) + 1, r, k, ch);
    pushup(rt);
  }
  inline int query(int rt, int l, int r, int L, int R) {
    if (L <= l && r <= R) return val[rt];
    int ans = 0;
    if (L <= ((l + r) >> 1))
      ans = max(ans, query(rt << 1, l, ((l + r) >> 1), L, R));
    if (R > ((l + r) >> 1))
      ans = max(ans, query(rt << 1 | 1, ((l + r) >> 1) + 1, r, L, R));
    return ans;
  }
  inline void find_k(int rt, int l, int r, int L, int R, int k) {
    if (val[rt] != k && L <= l && r <= R) return;
    if (l == r) {
      val[rt] = 0;
      return;
    }
    if (L <= ((l + r) >> 1)) find_k(rt << 1, l, ((l + r) >> 1), L, R, k);
    if (R > ((l + r) >> 1)) find_k(rt << 1 | 1, ((l + r) >> 1) + 1, r, L, R, k);
    pushup(rt);
  }
} t;
int dfn[maxn << 1], index_;
inline void dfs(int x, int f) {
  dfn[x] = ++index_;
  t.insert(1, 1, idx, dfn[x], p[x]);
  siz[x] = 1;
  for (int i = 1; i <= 18; i++) {
    if (!fa[x][i - 1]) break;
    fa[x][i] = fa[fa[x][i - 1]][i - 1];
  }
  for (int i = head[x], v; i; i = e[i].u) {
    v = e[i].v;
    if (v == f) continue;
    dep[v] = dep[x] + 1;
    fa[v][0] = x;
    dfs(v, x);
    siz[x] += siz[v];
  }
}
inline void kruskal() {
  std::sort(E + 1, E + m + 1, cmp);
  idx = n;
  for (int i = 1; i <= m; i++) {
    int fx = find(E[i].u), fy = find(E[i].v);
    if (fx == fy) continue;
    idx++;
    used[E[i].idx] = 1;
    ch[E[i].idx] = idx;
    add(idx, fx);
    add(idx, fy);
    bcj[fx] = idx;
    bcj[fy] = idx;
    cnt++;
    if (cnt == (n - 1)) break;
  }
  for (int i = 1; i <= n; i++)
    if (!dep[i]) dfs(find(i), 0);
}
inline int query(int x) {
  for (int i = 18; i >= 0; i--)
    if (fa[x][i] && (!tag[fa[x][i]])) x = fa[x][i];
  int Ans = t.query(1, 1, idx, dfn[x], dfn[x] + siz[x] - 1);
  t.find_k(1, 1, idx, dfn[x], dfn[x] + siz[x] - 1, Ans);
  return Ans;
}
int main() {
  read(n);
  read(m);
  read(q);
  for (int i = 1; i <= n; i++) read(p[i]);
  for (int i = 1; i <= (n << 1); i++) bcj[i] = i;
  for (int i = 1; i <= m; i++)
    read(E[i].u), read(E[i].v), E[i].t = (q + 1), E[i].idx = i;
  for (int i = 1; i <= q; i++) {
    read(opt[i]);
    read(x[i]);
    if (opt[i] == 2) E[x[i]].t = min(E[x[i]].t, i);
  }
  kruskal();
  for (int i = 1; i <= q; i++) {
    if (opt[i] == 2 && used[x[i]]) tag[ch[x[i]]] = 1;
    if (opt[i] == 1) printf("%d\n", query(x[i]));
  }
}
