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 = 1e9 + 7;
const int mod = 1e9 + 7;
long long int powmod(long long int a, long long int b) {
  long long int res = 1;
  a %= mod;
  assert(b >= 0);
  for (; b; b >>= 1) {
    if (b & 1) res = res * a % mod;
    a = a * a % mod;
  }
  return res;
}
int nxt() {
  int x;
  scanf("%d", &x);
  return x;
}
class UnionFind {
 private:
  vector<int> p;

 public:
  UnionFind(int N) {
    p.resize(N);
    iota((p).begin(), (p).end(), 0);
  }
  int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
  bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
  int unionSet(int i, int j) {
    if (!isSameSet(i, j)) {
      int x = findSet(i), y = findSet(j);
      int c = p.size();
      p.push_back(c);
      p[x] = c;
      p[y] = c;
      return c;
    }
    return -1;
  }
};
vector<vector<int> > adjlist;
vector<int> tin, tout;
int counter = 0;
void dfs(int u, int p) {
  tin[u] = ++counter;
  for (int v : adjlist[u]) {
    if (v == p) continue;
    dfs(v, u);
  }
  tout[u] = counter;
}
vector<int> c;
const int nax = 4e5;
struct segTree {
  int node[nax << 2];
  int build(int p, int l, int r) {
    if (l == r) {
      return node[p] = l;
    }
    int mid = (l + r) / 2;
    int a1 = build(p * 2 + 1, l, mid);
    int a2 = build(p * 2 + 2, mid + 1, r);
    return node[p] = c[a1] > c[a2] ? a1 : a2;
  }
  int query(int p, int l, int r, int a, int b) {
    if (r < a || l > b) return -1;
    if (l >= a && r <= b) return node[p];
    int mid = (l + r) / 2;
    int a1 = query(p * 2 + 1, l, mid, a, b);
    int a2 = query(p * 2 + 2, mid + 1, r, a, b);
    if (a1 == -1) return a2;
    if (a2 == -1) return a1;
    return c[a1] > c[a2] ? a1 : a2;
  }
  int erase(int p, int l, int r, int a) {
    if (r < a || l > a) return node[p];
    if (l == r) {
      c[l] = 0;
      return l;
    }
    int mid = (l + r) / 2;
    int a1 = erase(p * 2 + 1, l, mid, a);
    int a2 = erase(p * 2 + 2, mid + 1, r, a);
    if (a1 == -1) return node[p] = a2;
    if (a2 == -1) return node[p] = a1;
    return node[p] = c[a1] > c[a2] ? a1 : a2;
  }
} tree;
int main() {
  int n, m, q;
  cin >> n >> m >> q;
  vector<int> a(n);
  generate((a).begin(), (a).end(), nxt);
  vector<pair<int, int> > edges(m);
  for (int i = 0; i < m; i++) {
    int x = nxt(), y = nxt();
    x--, y--;
    edges[i].first = x, edges[i].second = y;
  }
  vector<pair<int, int> > query(q);
  set<int> s;
  for (int i = 0; i < q; i++) {
    cin >> query[i].first >> query[i].second;
    query[i].second--;
    if (query[i].first == 2) s.insert(query[i].second);
  }
  for (int i = 0; i < m; i++)
    if (s.count(i) == 0) query.push_back({2, i});
  adjlist.assign(n, vector<int>());
  UnionFind uf(n);
  vector<int> segq;
  for (int i = query.size() - 1; i >= 0; i--) {
    if (query[i].first == 1) {
      segq.push_back(uf.findSet(query[i].second));
    } else {
      int x = uf.findSet(edges[query[i].second].first);
      int y = uf.findSet(edges[query[i].second].second);
      int outcome = uf.unionSet(x, y);
      if (outcome != -1) {
        adjlist.push_back(vector<int>());
        adjlist[outcome].push_back(x);
        adjlist[outcome].push_back(y);
      }
    }
  }
  reverse((segq).begin(), (segq).end());
  tin.resize(adjlist.size());
  tout.resize(adjlist.size());
  for (int i = 0; i < adjlist.size(); i++)
    if (uf.findSet(i) == i) dfs(i, -1);
  c.assign(counter + 1, 0);
  for (int i = 0; i < n; i++) c[tin[i]] = a[i];
  tree.build(0, 0, counter);
  for (int x : segq) {
    int ans = tree.query(0, 0, counter, tin[x], tout[x]);
    if (ans != -1) {
      printf("%d\n", c[ans]);
      tree.erase(0, 0, counter, ans);
    } else
      puts("0");
  }
  return 0;
}
