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 MAX = 1e6 + 5;
vector<pair<int, int>> edges;
vector<pair<int, int>> queries;
int nodes[MAX], ds[MAX], currentNode;
bool dels[MAX];
vector<int> ady[MAX];
pair<int, int> stree[4 * MAX];
int idIni[MAX], idFin[MAX];
int dsFind(int v) {
  if (ds[v] == v) {
    return v;
  }
  return ds[v] = dsFind(ds[v]);
}
void dsJoin(int u, int v) {
  currentNode++;
  u = dsFind(u);
  v = dsFind(v);
  ds[currentNode] = currentNode;
  ds[u] = currentNode;
  ds[v] = currentNode;
  ady[currentNode].push_back(u);
  ady[currentNode].push_back(v);
}
pair<int, int> query(int n, int ini, int fin, int a, int b) {
  if (ini > b || fin < a) {
    return make_pair(INT_MIN, INT_MIN);
  } else if (ini >= a && fin <= b) {
    return stree[n];
  } else {
    int mid = (ini + fin) / 2;
    return max(query(n * 2, ini, mid, a, b),
               query(n * 2 + 1, mid + 1, fin, a, b));
  }
}
void update(int n, int ini, int fin, int p, int v) {
  if (ini > p || fin < p) {
    return;
  } else if (ini >= p && fin <= p) {
    stree[n] = make_pair(v, p);
  } else {
    int mid = (ini + fin) / 2;
    update(n * 2, ini, mid, p, v);
    update(n * 2 + 1, mid + 1, fin, p, v);
    stree[n] = max(stree[n * 2], stree[n * 2 + 1]);
  }
}
void dfs(int u) {
  static int id = 0;
  id++;
  idIni[u] = id;
  for (auto v : ady[u]) {
    dfs(v);
  }
  idFin[u] = id;
}
int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  memset(stree, -63, sizeof stree);
  int N, M, Q;
  cin >> N >> M >> Q;
  currentNode = N;
  for (int i = 1; i <= N; i++) {
    cin >> nodes[i];
  }
  edges.emplace_back(0, 0);
  queries.emplace_back(0, 0);
  for (int i = 0; i < M; i++) {
    int u, v;
    cin >> u >> v;
    edges.emplace_back(u, v);
  }
  for (int i = 0; i < Q; i++) {
    int t, v;
    cin >> t >> v;
    if (t == 2) {
      dels[v] = true;
    }
    queries.emplace_back(t, v);
  }
  for (int i = 1; i <= N; i++) {
    ds[i] = i;
  }
  for (int i = 1; i <= M; i++) {
    if (!dels[i]) {
      dsJoin(edges[i].first, edges[i].second);
    }
  }
  for (int i = Q; i > 0; i--) {
    int t = queries[i].first;
    int n = queries[i].second;
    if (t == 1) {
      queries[i].second = dsFind(n);
    } else {
      dsJoin(edges[n].first, edges[n].second);
    }
  }
  for (int i = 1; i < MAX; i++) {
    if (ds[i] == i) {
      dfs(i);
    }
  }
  for (int i = 1; i <= N; i++) {
    int p = idIni[i];
    update(1, 1, currentNode + 1, p, nodes[i]);
  }
  for (int i = 1; i <= Q; i++) {
    int t = queries[i].first;
    int n = queries[i].second;
    if (t == 1) {
      auto res = query(1, 1, currentNode + 1, idIni[n], idFin[n]);
      cout << res.first << "\n";
      update(1, 1, currentNode + 1, res.second, 0);
    }
  }
  return 0;
}
