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 double eps = 1e-10;
const double PI = 3.1415926535897932;
const int dir[4][2] = {-1, 0, 0, -1, 1, 0, 0, 1};
const int maxn = 5e5 + 5;
int n, m, q;
int w[maxn];
pair<int, int> edge[maxn];
int uset[maxn * 2];
vector<int> G[maxn * 2];
int pn;
bool del[maxn];
int tar[maxn * 2];
pair<int, int> dfn[maxn * 2];
int redfn[maxn * 2];
int id = 0;
pair<int, int> tree[maxn * 2];
struct node {
  int a, b;
  int ans;
} op[maxn];
int find(int x) {
  if (x != uset[x]) uset[x] = find(uset[x]);
  return uset[x];
}
void dfs(int a) {
  dfn[a].first = ++id;
  redfn[id] = a;
  for (int b : G[a]) dfs(b);
  dfn[a].second = id;
}
void build(int root, int a, int b) {
  if (a == b) {
    tree[root] = pair<int, int>(w[redfn[a]], redfn[a]);
    return;
  }
  int mid = a + b >> 1;
  build(root * 2, a, mid);
  build(root * 2 + 1, mid + 1, b);
  tree[root] = max(tree[root * 2], tree[root * 2 + 1]);
}
void change(int root, int a, int b, int x, int k) {
  if (a == b) {
    tree[root].first = k;
    return;
  }
  int mid = a + b >> 1;
  if (x <= mid)
    change(root * 2, a, mid, x, k);
  else
    change(root * 2 + 1, mid + 1, b, x, k);
  tree[root] = max(tree[root * 2], tree[root * 2 + 1]);
}
pair<int, int> query(int root, int a, int b, int x, int y) {
  if (x <= a && b <= y) return tree[root];
  if (b < x || y < a) return pair<int, int>(-1, -1);
  int mid = a + b >> 1;
  return max(query(root * 2, a, mid, x, y),
             query(root * 2 + 1, mid + 1, b, x, y));
}
int main() {
  scanf("%d%d%d", &n, &m, &q);
  pn = n;
  for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
  for (int i = 1; i <= m; i++) scanf("%d%d", &edge[i].first, &edge[i].second);
  for (int i = 1; i <= q; i++) {
    scanf("%d%d", &op[i].a, &op[i].b);
    if (op[i].a == 2) del[op[i].b] = true;
  }
  for (int i = 1; i <= n; i++) uset[i] = i;
  for (int i = 1; i <= m; i++)
    if (!del[i]) {
      uset[find(edge[i].first)] = find(edge[i].second);
    }
  for (int i = 1; i <= n; i++)
    if (uset[i] != i) {
      G[find(i)].push_back(i);
    }
  for (int i = q; i >= 1; i--) {
    if (op[i].a == 1)
      tar[i] = find(op[i].b);
    else {
      int a = edge[op[i].b].first, b = edge[op[i].b].second;
      if (find(a) == find(b)) continue;
      ++pn;
      uset[pn] = pn;
      G[pn].push_back(find(a));
      G[pn].push_back(find(b));
      uset[find(a)] = pn;
      uset[find(b)] = pn;
    }
  }
  for (int i = pn; i >= 1; i--)
    if (!dfn[i].first) dfs(i);
  build(1, 1, pn);
  for (int i = 1; i <= q; i++)
    if (op[i].a == 1) {
      int t = tar[i];
      pair<int, int> res = query(1, 1, pn, dfn[t].first, dfn[t].second);
      op[i].ans = res.first;
      change(1, 1, pn, dfn[res.second].first, 0);
    }
  for (int i = 1; i <= q; i++)
    if (op[i].a == 1) printf("%d\n", op[i].ans);
  return 0;
}
