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 = 100000000;
int N;
struct edge {
  int u;
  int v;
  int index;
};
struct query {
  int type;
  int eindex;
  int v;
};
struct node {
  int ind;
  int val;
};
const int maxN = 400009;
int parent[maxN];
vector<int> children[maxN];
int euler[maxN];
int L[maxN];
int R[maxN];
int tt;
void dfs(int v) {
  euler[tt] = v;
  L[v] = tt++;
  for (int w : children[v]) {
    dfs(w);
  }
  R[v] = tt;
}
int find(int u) {
  if (parent[u] == u) return u;
  return parent[u] = find(parent[u]);
}
void Union(int u, int v, int t) {
  int r1, r2;
  r1 = find(u);
  r2 = find(v);
  if (r1 == r2) return;
  N++;
  parent[r1] = N;
  parent[r2] = N;
  parent[N] = N;
  children[N].push_back(r1);
  children[N].push_back(r2);
}
void build(node seg[], int v, int tl, int tr, int a[]) {
  if (tl == tr) {
    seg[v].ind = tl;
    seg[v].val = a[euler[tl]];
    return;
  }
  int m = (tl + tr) / 2;
  build(seg, 2 * v, tl, m, a);
  build(seg, 2 * v + 1, m + 1, tr, a);
  if (seg[2 * v].val > seg[2 * v + 1].val) {
    seg[v] = seg[2 * v];
  } else
    seg[v] = seg[2 * v + 1];
}
void update(node seg[], int v, int tl, int tr, int i, int x) {
  if (i < tl || i > tr) return;
  if (tl == tr) {
    seg[v].val = x;
    seg[v].ind = tl;
    return;
  }
  int m = (tl + tr) / 2;
  update(seg, 2 * v, tl, m, i, x);
  update(seg, 2 * v + 1, m + 1, tr, i, x);
  if (seg[2 * v].val > seg[2 * v + 1].val) {
    seg[v] = seg[2 * v];
  } else
    seg[v] = seg[2 * v + 1];
}
node squery(node seg[], int v, int tl, int tr, int l, int r) {
  if (tr < l || tl > r) return {0, -inf};
  if (tl >= l && tr <= r) {
    return seg[v];
  }
  int m = (tl + tr) / 2;
  node a = squery(seg, 2 * v, tl, m, l, r);
  node b = squery(seg, 2 * v + 1, m + 1, tr, l, r);
  if (a.val > b.val) return a;
  return b;
}
signed main() {
  int M, Q;
  cin >> N >> M >> Q;
  int a[maxN];
  int i, j, k;
  tt = 1;
  for (i = 1; i < maxN; i++) {
    if (i > N)
      a[i] = 0;
    else
      cin >> a[i];
  }
  edge elist[M + 1];
  for (i = 1; i <= M; i++) {
    int u, v;
    cin >> u >> v;
    elist[i].u = u;
    elist[i].v = v;
    elist[i].index = i;
  }
  vector<query> queries;
  int done[M + 1];
  for (i = 1; i <= M; i++) done[i] = 0;
  while (Q--) {
    int type;
    cin >> type;
    query q;
    q.type = type;
    if (type == 1) {
      cin >> q.v;
    } else {
      cin >> q.eindex;
      done[q.eindex] = 1;
    }
    queries.push_back(q);
  }
  for (i = 1; i <= M; i++) {
    if (!done[i]) {
      query q;
      q.eindex = i;
      q.type = 2;
      queries.push_back(q);
    }
  }
  for (i = 1; i <= N; i++) {
    parent[i] = i;
  }
  reverse(queries.begin(), queries.end());
  for (i = 0; i < queries.size(); i++) {
    query q = queries[i];
    if (q.type == 2) {
      Union(elist[q.eindex].u, elist[q.eindex].v, i);
    } else {
      queries[i].v = find(queries[i].v);
    }
  }
  for (i = 1; i <= N; i++) {
    if (parent[i] == i) dfs(i);
  }
  node seg[4 * N + 8];
  build(seg, 1, 1, N, a);
  for (i = queries.size() - 1; i >= 0; i--) {
    query q = queries[i];
    if (q.type == 1) {
      int v = q.v;
      node temp = squery(seg, 1, 1, N, L[v], R[v]);
      cout << temp.val << "\n";
      update(seg, 1, 1, N, temp.ind, 0);
    }
  }
}
