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 = 4e5 + 5;
vector<int> adj[N];
vector<int> ans;
vector<int> a(N, 0);
vector<pair<int, int> > query;
vector<pair<int, int> > edge, nodes(N, {0, 0});
pair<int, int> seg[4 * N];
int f[N], sz[N], tin[N], tout[N], z, timer;
void dfs(int v, int p = -1) {
  tin[v] = ++timer;
  for (int to : adj[v]) {
    if (to != p) dfs(to, v);
  }
  tout[v] = timer;
}
struct SegmentTree {
  void build(int node, int l, int r, vector<pair<int, int> > &a) {
    if (l == r) {
      seg[node] = a[l];
      return;
    }
    int m = (l + r) >> 1;
    build(2 * node + 1, l, m, a);
    build(2 * node + 2, m + 1, r, a);
    seg[node] = max(seg[2 * node + 1], seg[2 * node + 2]);
  }
  void update(int node, int i, pair<int, int> val, int l, int r) {
    if (l == r) {
      seg[node] = val;
      return;
    }
    int m = (l + r) >> 1;
    if (i <= m)
      update(2 * node + 1, i, val, l, m);
    else
      update(2 * node + 2, i, val, m + 1, r);
    seg[node] = max(seg[2 * node + 1], seg[2 * node + 2]);
  }
  pair<int, int> query(int node, int sl, int sr, int ql, int qr) {
    if (sl > qr or sr < ql) return {0, 0};
    if (sl >= ql and sr <= qr) return seg[node];
    int m = (sl + sr) >> 1;
    pair<int, int> l = query(2 * node + 1, sl, m, ql, qr);
    pair<int, int> r = query(2 * node + 2, m + 1, sr, ql, qr);
    return max(l, r);
  }
};
void init(int n) {
  for (int i = 0; i < n; ++i) f[i] = i, sz[i] = 1;
}
int root(int x) {
  while (x != f[x]) {
    f[x] = f[f[x]];
    x = f[x];
  }
  return x;
}
bool merge(int x, int y) {
  int r_a = root(x), b = root(y);
  if (r_a == b) return true;
  if (sz[r_a] > sz[b]) swap(r_a, b);
  f[z] = z;
  f[r_a] = z;
  f[b] = z;
  adj[z].push_back(r_a);
  adj[z].push_back(b);
  ++z;
  return false;
}
bool isConnected(int x, int y) {
  if (root(x) == root(y))
    return true;
  else
    return false;
}
void solve() {
  memset(tin, -1, sizeof tin);
  memset(tout, -1, sizeof tout);
  int n, m, q;
  cin >> n >> m >> q;
  z = n;
  vector<bool> isPresent(m, 1);
  init(N);
  for (int i = 0; i < n; ++i) {
    cin >> a[i];
  }
  for (int i = 0; i < m; ++i) {
    int u, v;
    cin >> u >> v;
    --u, --v;
    edge.emplace_back(u, v);
  }
  for (int i = 0; i < q; ++i) {
    int t, u;
    cin >> t >> u;
    --u;
    query.emplace_back(t, u);
    if (t == 2) isPresent[u] = 0;
  }
  for (int i = 0; i < m; ++i) {
    if (isPresent[i]) {
      merge(edge[i].first, edge[i].second);
    }
  }
  reverse(query.begin(), query.end());
  vector<int> q_par(q);
  int j = q - 1;
  for (auto &[t, i] : query) {
    if (t == 2) {
      merge(edge[i].first, edge[i].second);
    } else {
      q_par[j] = root(i);
    }
    --j;
  }
  for (int i = 0; i <= z; ++i) {
    if (root(i) == i) {
      dfs(i);
    }
  }
  for (int i = 0; i <= z; ++i) {
    nodes[tin[i]] = {a[i], tin[i]};
  }
  reverse(query.begin(), query.end());
  SegmentTree st;
  st.build(0, 0, z, nodes);
  j = 0;
  for (auto &[t, i] : query) {
    if (t == 2) {
      ++j;
      continue;
    }
    int v = q_par[j];
    pair<int, int> s = st.query(0, 0, z, tin[v], tout[v]);
    ans.push_back(s.first);
    st.update(0, s.second, {0, 0}, 0, z);
    ++j;
  }
  for (int i : ans) cout << i << " ";
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  int t = 1;
  while (t--) {
    solve();
  }
}
