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 warning
using namespace std;
template <typename _Tp>
inline _Tp read(_Tp& x) {
  char c11 = getchar(), ob = 0;
  x = 0;
  while (c11 ^ '-' && !isdigit(c11)) c11 = getchar();
  if (c11 == '-') c11 = getchar(), ob = 1;
  while (isdigit(c11)) x = x * 10 + c11 - '0', c11 = getchar();
  if (ob) x = -x;
  return x;
}
const int inf = 0x3f3f3f3f;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const long long mod = 1e9 + 7;
const int maxn = 6e5 + 100;
long long qpow(long long a, long long b) {
  long long res = 1;
  while (b) {
    if (b & 1) res = res * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return res;
}
template <typename _Tp>
inline void Max(_Tp& x, _Tp y) {
  x = max(x, y);
}
template <typename _Tp>
inline void Min(_Tp& x, _Tp y) {
  x = min(x, y);
}
int discrete(vector<int>& vec) {
  sort(vec.begin(), vec.end());
  vec.erase(unique(vec.begin(), vec.end()), vec.end());
  return vec.size();
}
int n, m, q;
struct Edge {
  int u, v, c;
  bool operator<(const Edge& rhs) const { return c > rhs.c; }
};
int clk = 0;
int ind[maxn];
int outd[maxn];
int pn[maxn];
int arr[maxn];
struct Kruskal_Tree {
  int f[maxn][32];
  int fa[maxn];
  int tot = 0;
  vector<int> G[maxn];
  void init_fa(int n) {
    for (int i = 1; i <= (n); ++i) fa[i] = i;
  }
  int getfa(int x) { return fa[x] == x ? fa[x] : fa[x] = getfa(fa[x]); }
  void build(int n, vector<Edge>& vec) {
    init_fa(n);
    tot = n;
    sort(vec.begin(), vec.end());
    for (Edge& e : vec) {
      int u = e.u, v = e.v;
      int fu = getfa(u), fv = getfa(v);
      if (fu != fv) {
        int new_rt = ++tot;
        fa[fu] = fa[fv] = fa[new_rt] = new_rt;
        pn[new_rt] = e.c;
        G[new_rt].push_back(fv);
        G[new_rt].push_back(fu);
      }
    }
    queue<int> q;
    set<int> st;
    for (int i = 1; i <= tot; ++i) {
      int head = getfa(i);
      if (!st.count(head)) {
        st.insert(head);
        q.push(head);
      }
    }
    while (q.size() >= 2) {
      int v = q.front();
      q.pop();
      int u = q.front();
      q.pop();
      int new_rt = ++tot;
      fa[u] = fa[v] = fa[new_rt] = new_rt;
      G[new_rt].push_back(v);
      G[new_rt].push_back(u);
      pn[new_rt] = -inf;
      q.push(new_rt);
    }
    init_f(tot, 0);
    dfs(tot, 0);
  }
  void init_f(int x, int fa = -1) {
    f[x][0] = fa;
    for (int i = 1; i <= 30; ++i) {
      f[x][i] = f[f[x][i - 1]][i - 1];
    }
    for (int v : G[x]) init_f(v, x);
  }
  void dfs(int u, int fa = -1) {
    ind[u] = ++clk;
    if (u <= n) arr[ind[u]] = pn[u];
    for (int v : G[u]) {
      dfs(v, u);
    }
    outd[u] = clk;
  }
  int find_root(int x, int cost) {
    int u = x;
    for (int i = 30; i >= 0; --i) {
      if (pn[f[u][i]] >= cost) {
        u = f[u][i];
      }
    }
    return u;
  }
} kru_tr;
int idx, mv;
struct SegmentTree {
  int maxv[maxn << 1];
  int id[maxn << 1];
  void pushup(int o) {
    maxv[o] = max(maxv[(o << 1)], maxv[(o << 1 | 1)]);
    if (maxv[(o << 1)] > maxv[(o << 1 | 1)])
      id[o] = id[(o << 1)];
    else
      id[o] = id[(o << 1 | 1)];
  }
  void build(int o, int l, int r) {
    if (l == r) {
      maxv[o] = arr[l];
      id[o] = l;
    } else {
      build((o << 1), l, ((l + r) >> 1));
      build((o << 1 | 1), ((l + r) >> 1) + 1, r);
      pushup(o);
    }
  }
  void update(int o, int x, int l, int r, int v) {
    if (l == r) {
      maxv[o] = v;
    } else {
      if (x <= ((l + r) >> 1)) {
        update((o << 1), x, l, ((l + r) >> 1), v);
      } else {
        update((o << 1 | 1), x, ((l + r) >> 1) + 1, r, v);
      }
      pushup(o);
    }
  }
  void query(int o, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) {
      if (maxv[o] > mv) {
        mv = maxv[o];
        idx = id[o];
      }
    } else {
      if (ql <= ((l + r) >> 1)) {
        query((o << 1), l, ((l + r) >> 1), ql, qr);
      }
      if (qr > ((l + r) >> 1)) {
        query((o << 1 | 1), ((l + r) >> 1) + 1, r, ql, qr);
      }
    }
  }
} seg_tr;
int val;
void Query(int x) {
  mv = idx = -1;
  int rt = kru_tr.find_root(x, val);
  int l = ind[rt], r = outd[rt];
  int nn = kru_tr.tot;
  seg_tr.query(1, 1, nn, l, r);
  seg_tr.update(1, idx, 1, nn, 0);
  printf("%d\n", mv);
}
int tag[maxn];
Edge edge[maxn];
vector<pair<int, int> > asks;
signed main() {
  cin >> n >> m >> q;
  for (int i = 1; i <= (n); ++i) cin >> pn[i];
  for (int i = 1; i <= (m); ++i) {
    read(edge[i].u);
    read(edge[i].v);
    edge[i].c = inf;
  }
  int x, y;
  int tms = 0;
  for (int i = 1; i <= (q); ++i) {
    read(x);
    read(y);
    asks.push_back(make_pair(x, y));
    if (x == 2) {
      tms++;
      edge[y].c -= tms;
    }
  }
  vector<Edge> vec;
  for (int i = 1; i <= (m); ++i) vec.push_back(edge[i]);
  kru_tr.build(n, vec);
  seg_tr.build(1, 1, kru_tr.tot);
  val = inf - tms;
  for (pair<int, int> pa : asks) {
    int x = pa.first, y = pa.second;
    if (x == 1) {
      Query(y);
    } else {
      val++;
    }
  }
  return 0;
}
