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 N = 2e5 + 3, M = 3e5 + 3, Q = 5e5 + 3;
const int NEW_N = N + Q;
int n, m, q, orgN, arr[N];
int currentDeletedEdge[N];
int dsu[NEW_N], vertexToQuery[Q];
int in[NEW_N], out[NEW_N], cnt;
pair<int, int> T[4 * NEW_N];
vector<int> adj[N];
pair<int, int> edges[M], queries[Q];
int getRootDSU(int x) { return dsu[x] < 0 ? x : getRootDSU(dsu[x]); }
pair<int, int> max(pair<int, int> a, pair<int, int> b) {
  return a.first < b.first ? b : a;
}
void mergeDSU(int u, int v, int forceOrder = 0) {
  u = getRootDSU(u), v = getRootDSU(v);
  if (u == v) return;
  if (!forceOrder && arr[u] < arr[v]) swap(u, v);
  dsu[u] += dsu[v], dsu[v] = u;
  if (forceOrder == 0) {
    adj[u].push_back(v);
  }
}
void updateIT(int i, int l, int r, int pos, int val) {
  if (l > pos || pos > r) return;
  if (l == r) {
    T[i] = {val, pos};
    return;
  }
  int mid = l + r >> 1;
  updateIT(i * 2, l, mid, pos, val);
  updateIT(i * 2 + 1, mid + 1, r, pos, val);
  T[i] = max(T[i * 2], T[i * 2 + 1]);
}
pair<int, int> getIT(int i, int l, int r, int L, int R) {
  if (l > R || L > r) return {0, 0};
  if (L <= l && r <= R) return T[i];
  int mid = l + r >> 1;
  return max(getIT(i * 2, l, mid, L, R), getIT(i * 2 + 1, mid + 1, r, L, R));
}
void dfs(int u) {
  in[u] = ++cnt;
  for (int v : adj[u]) {
    dfs(v);
  }
  out[u] = cnt;
}
pair<int, int> queryForSubtree(int u) {
  int left = in[u], right = out[u];
  return getIT(1, 1, n, left, right);
}
void buildEulerTour() {
  for (int i = n; i; i--) {
    if (in[i] > 0) continue;
    dfs(i);
  }
  for (int i = 1; i <= orgN; i++) {
    updateIT(1, 1, n, in[i], arr[i]);
  }
}
void solve() {
  orgN = n;
  memset(dsu, -1, sizeof dsu);
  for (int i = 1; i <= m; i++) {
    if (currentDeletedEdge[i]) continue;
    int u = edges[i].first, v = edges[i].second;
    mergeDSU(u, v);
  }
  for (int i = q; i; i--) {
    int type = queries[i].first;
    if (type == 1) {
      int vertex = queries[i].second;
      vertexToQuery[i] = getRootDSU(vertex);
    } else {
      int id = queries[i].second;
      int u = getRootDSU(edges[id].first), v = getRootDSU(edges[id].second);
      if (u == v) continue;
      n++;
      adj[n].push_back(u);
      adj[n].push_back(v);
      mergeDSU(n, u, 1), mergeDSU(n, v, 1);
    }
  }
  buildEulerTour();
  for (int i = 1; i <= q; i++) {
    if (queries[i].first != 1) continue;
    int v = vertexToQuery[i];
    pair<int, int> res = queryForSubtree(v);
    cout << res.first << '\n';
    if (res.first > 0) updateIT(1, 1, n, res.second, 0);
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  if (fopen("trash.inp", "r")) {
    freopen("trash.inp", "r", stdin);
    freopen("trash.out", "w", stdout);
  }
  cin >> n >> m >> q;
  for (int i = 1; i <= n; i++) {
    cin >> arr[i];
  }
  for (int i = 1; i <= m; i++) {
    int u, v;
    cin >> u >> v;
    edges[i] = {u, v};
  }
  for (int i = 1; i <= q; i++) {
    int u, v;
    cin >> u >> v;
    queries[i] = {u, v};
    if (u == 2) {
      currentDeletedEdge[v] = 1;
    }
  }
  solve();
}
