#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
using namespace std;
const double PI = acos(-1.0);
struct UF {
  vector<long long> p, r;
  long long conjuntos = 0;
  UF(long long n) {
    conjuntos = n;
    for (long long i = 0; i < n; i++) {
      p.push_back(i);
      r.push_back(0);
    }
  }
  long long find(long long x) { return p[x] = p[x] == x ? x : find(p[x]); }
  void join(long long x, long long y) {
    x = find(x);
    y = find(y);
    if (x != y) {
      conjuntos--;
      if (r[x] >= r[y]) {
        if (r[x] == r[y]) r[x]++;
        p[y] = x;
      } else
        p[x] = y;
    }
  }
};
struct SegmentTree {
  vector<pair<long long, long long> > ST;
  long long N;
  SegmentTree(vector<long long>& A) {
    N = A.size();
    ST.resize(4 * N);
    build(1, 0, N - 1, A);
  }
  void build(long long n, long long l, long long r, vector<long long>& A) {
    if (l == r) {
      ST[n] = {A[r], l};
      return;
    }
    build(2 * n, l, (l + r) / 2, A);
    build(2 * n + 1, (l + r) / 2 + 1, r, A);
    ST[n] = max(ST[2 * n], ST[2 * n + 1]);
  }
  pair<long long, long long> query(long long i, long long j) {
    return query(1, 0, N - 1, i, j);
  }
  pair<long long, long long> query(long long n, long long l, long long r,
                                   long long i, long long j) {
    if (r < i || j < l) return {-1, -1};
    if (i <= l && r <= j) return ST[n];
    return max(query(2 * n, l, (l + r) / 2, i, j),
               query(2 * n + 1, (l + r) / 2 + 1, r, i, j));
  }
  void update(long long i, long long v) { return update(1, 0, N - 1, i, v); }
  void update(long long n, long long l, long long r, long long i, long long v) {
    if (i < l || r < i) return;
    if (l == r) {
      ST[n].first = v;
      return;
    }
    update(2 * n, l, (l + r) / 2, i, v);
    update(2 * n + 1, (l + r) / 2 + 1, r, i, v);
    ST[n] = max(ST[2 * n], ST[2 * n + 1]);
  }
};
long long cont = -1, n;
vector<long long> L(400005, -1), R(400005, -1), ID(400005, -1);
vector<long long> arr;
void dfs(vector<vector<long long> >& g, vector<long long>& vis,
         vector<long long>& c, long long in, long long id) {
  if (!vis[in]) {
    vis[in] = 1;
    cont++;
    if (in >= n)
      arr.push_back(-1);
    else
      arr.push_back(c[in]);
    L[in] = cont;
    ID[in] = id;
    for (int i = 0; i < g[in].size(); i++) {
      if (!vis[g[in][i]]) dfs(g, vis, c, g[in][i], id);
    }
    R[in] = cont;
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  long long m, q, x, y;
  cin >> n >> m >> q;
  vector<long long> c;
  for (int i = 0; i < n; i++) {
    cin >> x;
    c.push_back(x);
  }
  vector<pair<long long, long long> > ar;
  vector<long long> visar(m, 0);
  for (int i = 0; i < m; i++) {
    cin >> x >> y;
    ar.push_back({x - 1, y - 1});
  }
  vector<pair<long long, long long> > Q;
  for (int i = 0; i < q; i++) {
    cin >> x >> y;
    Q.push_back({x, y - 1});
    if (x == 2) visar[y - 1] = 1;
  }
  for (int i = 0; i < m; i++) {
    if (!visar[i]) Q.push_back({2, i});
  }
  UF uf(400005);
  long long in = n;
  vector<vector<long long> > g(400005, vector<long long>(0));
  vector<long long> que(Q.size(), -1);
  for (int i = Q.size() - 1; i >= 0; i--) {
    if (Q[i].first == 2) {
      long long x = uf.find(ar[Q[i].second].first),
                y = uf.find(ar[Q[i].second].second);
      if (x == y) continue;
      g[in].push_back(x);
      g[in].push_back(y);
      uf.p[x] = in;
      uf.p[y] = in;
      in++;
    } else {
      long long x = uf.find(Q[i].second);
      que[i] = x;
    }
  }
  set<long long> nod;
  for (int i = 0; i < n; i++) {
    nod.insert(uf.find(i));
  }
  long long id = 0;
  vector<SegmentTree> STs;
  for (auto it : nod) {
    arr.clear();
    vector<long long> vis(in, 0);
    cont = -1;
    dfs(g, vis, c, it, id);
    SegmentTree ST(arr);
    STs.push_back(ST);
    id++;
  }
  for (int i = 0; i < Q.size(); i++) {
    if (Q[i].first == 1) {
      long long id, v;
      tie(v, id) = STs[ID[que[i]]].query(L[que[i]], R[que[i]]);
      cout << v << "\n";
      STs[ID[que[i]]].update(id, 0);
    }
  }
}
