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>
using namespace std;
const int MAXN = 400005;
const int MAXM = 300005;
const int MAXQ = 5e5 + 5;
int n, m, q, p[MAXN];
struct Edge {
  int u, v, t;
  bool operator<(const Edge &a) const { return t > a.t; }
} graph[MAXM];
struct Query {
  int op, v;
} query[MAXQ];
struct Edge2 {
  int v, next;
} pool[MAXN];
int fa[MAXN], anc[MAXN][20], nt, ww[MAXN], head[MAXN], nn;
void addEdge(int u, int v) {
  pool[++nn].v = v;
  pool[nn].next = head[u];
  head[u] = nn;
}
int find(int x) {
  if (fa[x] == x) return x;
  return fa[x] = find(fa[x]);
}
void tree() {
  sort(graph + 1, graph + m + 1);
  nt = n;
  for (int i = 1; i <= n; ++i) {
    fa[i] = i;
  }
  for (int i = 1; i <= m; ++i) {
    int u = graph[i].u;
    int v = graph[i].v;
    int w = graph[i].t;
    int fu = find(fa[u]);
    int fv = find(fa[v]);
    if (fu != fv) {
      nt++;
      fa[fu] = fa[fv] = fa[nt] = anc[fu][0] = anc[fv][0] = nt;
      ww[nt] = w;
      addEdge(nt, fu);
      addEdge(nt, fv);
    }
  }
  nt++;
  for (int i = 1; i < nt; ++i) {
    if (fa[i] == i) {
      fa[i] = nt;
      anc[i][0] = nt;
      addEdge(nt, i);
    }
  }
}
int leaf[MAXN], dt, lr[MAXN], rr[MAXN];
void dfs(int u) {
  lr[u] = dt;
  for (int i = 1; i < 20; ++i) {
    anc[u][i] = anc[anc[u][i - 1]][i - 1];
  }
  if (head[u] == 0) {
    dt++;
    rr[u] = dt;
    leaf[dt] = p[u];
    return;
  }
  for (int i = head[u]; i; i = pool[i].next) {
    int v = pool[i].v;
    dfs(v);
  }
  rr[u] = dt;
}
int ma[MAXN * 4];
inline int lc(int p) { return p << 1; }
inline int rc(int p) { return p << 1 | 1; }
void pushUp(int p) { ma[p] = max(ma[lc(p)], ma[rc(p)]); }
void buildTree(int p, int l, int r) {
  if (l == r) {
    ma[p] = leaf[l];
    return;
  }
  int mid = (l + r) >> 1;
  buildTree(lc(p), l, mid);
  buildTree(rc(p), mid + 1, r);
  pushUp(p);
}
int queryMax(int p, int l, int r, int ql, int qr) {
  if (ma[p] == 0) return 0;
  if (ql <= l && r <= qr) {
    return ma[p];
  }
  int mid = (l + r) >> 1;
  int ans = 0;
  if (ql <= mid) {
    ans = max(ans, queryMax(lc(p), l, mid, ql, qr));
  }
  if (mid < qr) {
    ans = max(ans, queryMax(rc(p), mid + 1, r, ql, qr));
  }
  return ans;
}
void update(int p, int l, int r, int ql, int qr, int d) {
  if (l == r) {
    ma[p] = 0;
    return;
  }
  int mid = (l + r) >> 1;
  if (queryMax(lc(p), l, mid, ql, qr) == d) {
    update(lc(p), l, mid, ql, qr, d);
  } else {
    update(rc(p), mid + 1, r, ql, qr, d);
  }
  pushUp(p);
}
int findRoot(int u, int time) {
  for (int i = 19; i >= 0; --i) {
    if (ww[anc[u][i]] > time) {
      u = anc[u][i];
    }
  }
  return u;
}
int main() {
  scanf("%d%d%d", &n, &m, &q);
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &p[i]);
  }
  for (int i = 1; i <= m; ++i) {
    scanf("%d%d", &graph[i].u, &graph[i].v);
    graph[i].t = MAXQ;
  }
  for (int i = 1; i <= q; ++i) {
    scanf("%d%d", &query[i].op, &query[i].v);
    if (query[i].op == 2) {
      graph[query[i].v].t = i;
    }
  }
  tree();
  dfs(nt);
  buildTree(1, 1, n);
  for (int i = 1; i <= q; ++i) {
    if (query[i].op == 1) {
      int v = findRoot(query[i].v, i);
      int ans = queryMax(1, 1, n, lr[v] + 1, rr[v]);
      printf("%d\n", ans);
      if (ans != 0) {
        update(1, 1, n, lr[v] + 1, rr[v], ans);
      }
    }
  }
  return 0;
}
