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;
template <typename T>
void chkmax(T &x, T y) {
  x = x > y ? x : y;
}
template <typename T>
void chkmin(T &x, T y) {
  x = x > y ? y : x;
}
template <typename T>
void add(T &x, T y, T mod) {
  x = x + y > mod ? x + y - mod : x + y;
}
template <typename T>
void sub(T &x, T y, T mod) {
  x = x - y < 0 ? x - y + mod : x - y;
}
template <typename T>
void multi(T &x, T y, T mod) {
  x = 1ll * x * y % mod;
}
const int INF = 2139062143;
template <typename T>
void read(T &x) {
  x = 0;
  bool f = 1;
  char ch;
  do {
    ch = getchar();
    if (ch == '-') f = 0;
  } while (ch > '9' || ch < '0');
  do {
    x = x * 10 + ch - '0';
    ch = getchar();
  } while (ch >= '0' && ch <= '9');
  x = f ? x : -x;
}
template <typename T>
void write(T x) {
  if (x < 0) x = ~x + 1, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
const int N = 1e6 + 7;
struct QUERY {
  int opt, u;
} Q[N];
struct Node {
  int u, v;
} edge[N];
struct EDGE {
  int to, nxt;
} e[N << 1];
struct Segment_Tree {
  int l, r;
  pair<int, int> dat;
} t[N << 2];
int n, m, q, cnt, E, dfn_clock, p[N], sz[N], fa[N], id[N], pos[N], dfn[N],
    head[N];
bool vis[N];
inline void addedge(int u, int v) {
  e[++E].to = v;
  e[E].nxt = head[u];
  head[u] = E;
}
inline void build(int p, int l, int r) {
  t[p].l = l;
  t[p].r = r;
  if (l == r) return;
  int mid = (l + r) >> 1;
  build((p << 1), l, mid);
  build((p << 1 | 1), mid + 1, r);
}
pair<int, int> merge(pair<int, int> a, pair<int, int> b) {
  if (a.first > b.first)
    return a;
  else
    return b;
}
inline void modify(int p, int pos, int val) {
  if (t[p].l == t[p].r) return (void)(t[p].dat = make_pair(val, t[p].l));
  int mid = (t[p].l + t[p].r) >> 1;
  if (pos <= mid)
    modify((p << 1), pos, val);
  else
    modify((p << 1 | 1), pos, val);
  t[p].dat = merge(t[(p << 1)].dat, t[(p << 1 | 1)].dat);
}
inline pair<int, int> query(int p, int l, int r) {
  if (l <= t[p].l && t[p].r <= r) return t[p].dat;
  int mid = (t[p].l + t[p].r) >> 1;
  if (r <= mid) return query((p << 1), l, r);
  if (l > mid) return query((p << 1 | 1), l, r);
  return merge(query((p << 1), l, r), query((p << 1 | 1), l, r));
}
inline int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }
inline void merge(int u, int v) {
  u = find(u), v = find(v);
  if (u == v) return;
  ++cnt;
  fa[cnt] = fa[u] = fa[v] = cnt;
  addedge(cnt, u);
  addedge(cnt, v);
}
inline void dfs(int u) {
  dfn[u] = ++dfn_clock;
  sz[u] = 1;
  for (int i = head[u]; i; i = e[i].nxt) {
    int v = e[i].to;
    dfs(v);
    sz[u] += sz[v];
  }
}
int main() {
  read(n);
  read(m);
  read(q);
  for (int i = 1; i <= n; i++) read(p[i]);
  for (int i = 1; i <= m; i++) read(edge[i].u), read(edge[i].v);
  for (int i = 1; i <= q; i++) {
    read(Q[i].opt), read(Q[i].u);
    if (Q[i].opt == 2) vis[Q[i].u] = true;
  }
  for (int i = 1; i <= n; i++) fa[i] = i;
  cnt = n;
  for (int i = 1; i <= m; i++)
    if (!vis[i]) merge(edge[i].u, edge[i].v);
  for (int i = q; i >= 1; i--) {
    if (Q[i].opt == 1)
      pos[i] = find(Q[i].u);
    else
      merge(edge[Q[i].u].u, edge[Q[i].u].v);
  }
  ++cnt;
  for (int i = 1; i < cnt; i++)
    if (i == find(i)) addedge(cnt, i);
  dfs(cnt);
  for (int i = 1; i <= n; i++) cerr << dfn[i] << endl;
  build(1, 1, cnt);
  for (int i = 1; i <= n; i++) modify(1, dfn[i], p[i]);
  for (int i = 1; i <= q; i++) {
    if (Q[i].opt == 2) continue;
    pair<int, int> pii = query(1, dfn[pos[i]], dfn[pos[i]] + sz[pos[i]] - 1);
    printf("%d\n", pii.first);
    modify(1, pii.second, 0);
  }
  return 0;
}
