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 inf = 0x3f3f3f3f;
const int N = 1e6 + 100;
int n, m, q;
struct Qu {
  int op, x;
} qu[N];
struct Edge {
  int u, v, w;
  bool operator<(const Edge& t) const { return w < t.w; }
} edge[N];
struct Max {
  int val, pos;
  Max() {}
  Max(int val, int pos) : val(val), pos(pos) {}
  static Max inf() { return Max(-0x3f3f3f3f, 0); }
  bool operator<(const Max& t) const { return val < t.val; }
};
struct Node {
  int l, r;
  Max mmax;
} tree[N << 2];
int a[N], f[N], val[N], dp[N][25], L[N], R[N], id[N], tot;
vector<int> node[N];
void pushup(int k) {
  tree[k].mmax = max(tree[k << 1].mmax, tree[k << 1 | 1].mmax);
}
void build(int k, int l, int r) {
  tree[k].l = l;
  tree[k].r = r;
  if (l == r) {
    tree[k].mmax.val = a[id[l]];
    tree[k].mmax.pos = l;
    return;
  }
  int mid = l + r >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
  pushup(k);
}
void update(int k, int pos) {
  if (tree[k].l == tree[k].r) {
    tree[k].mmax.val = 0;
    return;
  }
  int mid = tree[k].l + tree[k].r >> 1;
  if (pos <= mid)
    update(k << 1, pos);
  else
    update(k << 1 | 1, pos);
  pushup(k);
}
Max query(int k, int l, int r) {
  if (tree[k].l > r || tree[k].r < l) return Max::inf();
  if (tree[k].l >= l && tree[k].r <= r) return tree[k].mmax;
  return max(query(k << 1, l, r), query(k << 1 | 1, l, r));
}
void dfs(int u, int fa) {
  dp[u][0] = fa;
  for (int i = 1; i <= 20; i++) dp[u][i] = dp[dp[u][i - 1]][i - 1];
  L[u] = ++tot;
  id[tot] = u;
  for (auto v : node[u]) dfs(v, u);
  R[u] = tot;
}
int get_pos(int u, int up) {
  for (int i = 20; i >= 0; i--)
    if (dp[u][i] != 0 && val[dp[u][i]] <= up) u = dp[u][i];
  return u;
}
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
int Ex_Kruskal() {
  for (int i = 1; i <= n << 1; i++) f[i] = i;
  int index = n;
  sort(edge + 1, edge + 1 + m);
  for (int i = 1; i <= m; i++) {
    int xx = find(edge[i].u), yy = find(edge[i].v);
    if (xx != yy) {
      f[xx] = f[yy] = ++index;
      val[index] = edge[i].w;
      node[index].push_back(xx);
      node[index].push_back(yy);
    }
  }
  int last = 1;
  for (int i = 1; i <= n; i++) {
    int xx = find(last), yy = find(i);
    if (xx != yy) {
      f[xx] = f[yy] = ++index;
      val[index] = inf;
      node[index].push_back(xx);
      node[index].push_back(yy);
      last = index;
    }
  }
  return index;
}
int main() {
  scanf("%d%d%d", &n, &m, &q);
  for (int i = 1; i <= n; i++) scanf("%d", a + i);
  for (int i = 1; i <= m; i++) {
    scanf("%d%d", &edge[i].u, &edge[i].v);
    edge[i].w = 0;
  }
  int val = inf;
  for (int i = 1; i <= q; i++) {
    scanf("%d%d", &qu[i].op, &qu[i].x);
    if (qu[i].op == 2) edge[qu[i].x].w = --val;
  }
  int root = Ex_Kruskal();
  dfs(root, 0);
  build(1, 1, root);
  val = inf - 1;
  for (int i = 1; i <= q; i++) {
    if (qu[i].op == 1) {
      int x = get_pos(qu[i].x, val);
      Max ans = query(1, L[x], R[x]);
      printf("%d\n", ans.val);
      update(1, ans.pos);
    } else
      val--;
  }
  return 0;
}
