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 nmax = 5e5 + 42;
struct query {
  int type, node;
};
query inp[nmax];
int n, m, q;
pair<int, int> edges[nmax];
int p[nmax];
bool blocked[nmax];
vector<int> comp[nmax];
int root[nmax];
vector<int> cut_into[nmax];
void my_merge(int u, int v) {
  u = root[u];
  v = root[v];
  if (u == v) return;
  if (comp[u].size() < comp[v].size()) swap(u, v);
  root[v] = u;
  for (auto w : comp[v]) {
    comp[u].push_back(w);
    root[w] = u;
  }
}
set<pair<int, int> > active[nmax * 2];
int main() {
  scanf("%i%i%i", &n, &m, &q);
  for (int i = 1; i <= n; i++) scanf("%i", &p[i]);
  for (int i = 1; i <= m; i++) scanf("%i%i", &edges[i].first, &edges[i].second);
  for (int i = 1; i <= q; i++) {
    scanf("%i%i", &inp[i].type, &inp[i].node);
    if (inp[i].type == 2) blocked[inp[i].node] = 1;
  }
  for (int i = 1; i <= n; i++) {
    root[i] = i;
    comp[i] = {i};
  }
  for (int i = 1; i <= m; i++)
    if (blocked[i] == 0) my_merge(edges[i].first, edges[i].second);
  for (int i = q; i >= 1; i--) {
    if (inp[i].type == 1) continue;
    int u = edges[inp[i].node].first;
    int v = edges[inp[i].node].second;
    if (root[u] == root[v]) continue;
    if (comp[root[u]].size() < comp[root[v]].size()) swap(u, v);
    for (auto w : comp[root[v]]) {
      cut_into[i].push_back(w);
    }
    my_merge(u, v);
  }
  for (int i = 1; i <= n; i++) {
    active[root[i]].insert({p[i], i});
  }
  int pointer = n;
  for (int i = 1; i <= q; i++)
    if (inp[i].type == 1) {
      set<pair<int, int> >::iterator it = active[root[inp[i].node]].end();
      it--;
      int node = (*it).second;
      printf("%i\n", p[node]);
      active[root[inp[i].node]].erase(it);
      p[node] = 0;
      active[root[inp[i].node]].insert({p[node], node});
    } else {
      if (cut_into[i].size() == 0) continue;
      int root_now = root[inp[i].node];
      pointer++;
      for (auto w : cut_into[i]) active[root_now].erase({p[w], w});
      for (auto w : cut_into[i]) {
        active[pointer].insert({p[w], w});
        root[w] = pointer;
        comp[pointer].push_back(w);
      }
    }
  return 0;
}
