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>
#pragma GCC optimize("Ofast, unroll-loops", "omit-frame-pointer", "inline")
#pragma GCC option("arch=native", "tune=native", "no-zero-upper")
#pragma GCC target( \
    "sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native,avx2")
using namespace std;
using ll = long long;
using ull = unsigned long long;
using ld = long double;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
ll getrnd(ll l, ll r) { return uniform_int_distribution<ll>(l, r)(rng); }
template <typename T1, typename T2>
inline bool relax(T1& a, const T2& b) {
  return a > b ? a = b, true : false;
}
template <typename T1, typename T2>
inline bool strain(T1& a, const T2& b) {
  return a < b ? a = b, true : false;
}
const int N = 1e6 + 3;
int a[N], wh[N], p[N], qrem[N], was[N], tin[N], sz[N], euler[N], tree[4 * N],
    timer = 0;
vector<int> graph[N];
int find(int v) { return v == p[v] ? v : (p[v] = find(p[v])); }
void dfs(int v) {
  was[v] = 1;
  sz[v] = 1;
  tin[v] = timer++;
  euler[tin[v]] = a[v];
  for (int to : graph[v]) {
    dfs(to);
    sz[v] += sz[to];
  }
}
void build(int v, int tl, int tr) {
  if (tl == tr)
    tree[v] = euler[tl];
  else {
    int tm = (tl + tr) / 2;
    build(2 * v, tl, tm);
    build(2 * v + 1, tm + 1, tr);
    tree[v] = max(tree[2 * v], tree[2 * v + 1]);
  }
}
void update(int v, int tl, int tr, int pos, int val) {
  if (tl == tr)
    tree[v] = val;
  else {
    int tm = (tl + tr) / 2;
    if (pos <= tm)
      update(2 * v, tl, tm, pos, val);
    else
      update(2 * v + 1, tm + 1, tr, pos, val);
    tree[v] = max(tree[2 * v], tree[2 * v + 1]);
  }
}
int get(int v, int tl, int tr, int l, int r) {
  if (l > r) return 0;
  if (tl == l && tr == r)
    return tree[v];
  else {
    int tm = (tl + tr) / 2;
    return max(get(2 * v, tl, tm, l, min(r, tm)),
               get(2 * v + 1, tm + 1, tr, max(l, tm + 1), r));
  }
}
void solve() {
  int n, m, q;
  cin >> n >> m >> q;
  iota(p, p + 2 * N, 0);
  for (int i = 0; i < n; ++i) cin >> a[i], wh[a[i]] = i;
  vector<pair<int, int>> edg(m);
  for (int i = 0; i < m; ++i) {
    cin >> edg[i].first >> edg[i].second;
    --edg[i].first, --edg[i].second;
  }
  vector<int> del(m);
  vector<pair<int, int>> qs;
  for (int i = 0; i < q; ++i) {
    int t, x;
    cin >> t >> x;
    qs.emplace_back(t, x - 1);
    if (t == 2) del[x - 1] = 1;
  }
  int num = n;
  auto add_edge = [&](int a, int b) {
    a = find(a);
    b = find(b);
    if (a != b) {
      p[a] = num;
      p[b] = num;
      graph[num].emplace_back(a);
      graph[num].emplace_back(b);
      ++num;
    }
  };
  for (int i = 0; i < m; ++i) {
    if (!del[i]) add_edge(edg[i].first, edg[i].second);
  }
  for (int i = q - 1; i >= 0; --i) {
    auto [t, x] = qs[i];
    if (t == 1) {
      qrem[i] = find(x);
    } else {
      add_edge(edg[x].first, edg[x].second);
    }
  }
  for (int i = 0; i < n; ++i) {
    int v = find(i);
    if (!was[v]) dfs(v);
  }
  build(1, 0, num - 1);
  vector<int> ans;
  for (int i = 0; i < q; ++i) {
    auto [t, x] = qs[i];
    if (t == 1) {
      int mxpar = qrem[i];
      int res = get(1, 0, num - 1, tin[mxpar], tin[mxpar] + sz[mxpar] - 1);
      if (res > 0) update(1, 0, num - 1, tin[wh[res]], 0);
      ans.emplace_back(res);
    }
  }
  for (int x : ans) cout << x << '\n';
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(nullptr);
  cout.tie(nullptr);
  srand(time(0));
  int t = 1;
  while (t--) solve();
  return 0;
}
