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 comment(linker, "/STACK:256777216")
using namespace std;
const int MAXN = 8e5;
const int MOD = 998244353;
int values[MAXN];
struct SegmentTree {
  int max_index[MAXN];
  void initialize(int l, int r, int index) {
    if (l == r) {
      max_index[index] = l;
      return;
    }
    int med = (l + r) >> 1;
    initialize(l, med, index * 2 + 1);
    initialize(med + 1, r, index * 2 + 2);
    max_index[index] =
        values[max_index[index * 2 + 1]] > values[max_index[index * 2 + 2]]
            ? max_index[index * 2 + 1]
            : max_index[index * 2 + 2];
  }
  SegmentTree(int n) { initialize(0, n - 1, 0); }
  int get_max(int l, int r, int l1, int r1, int index) {
    if (l == l1 && r == r1) {
      return max_index[index];
    }
    int med = (l + r) >> 1;
    vector<int> indexes;
    if (l1 <= med) {
      indexes.push_back(get_max(l, med, l1, min(r1, med), index * 2 + 1));
    }
    if (r1 > med) {
      indexes.push_back(
          get_max(med + 1, r, max(med + 1, l1), r1, index * 2 + 2));
    }
    if (indexes.size() == 1) return indexes[0];
    return values[indexes[0]] > values[indexes[1]] ? indexes[0] : indexes[1];
  }
  void update(int l, int r, int upd_ind, int ind) {
    if (l == r) {
      return;
    }
    int med = (l + r) >> 1;
    if (upd_ind <= med) {
      update(l, med, upd_ind, ind * 2 + 1);
    } else {
      update(med + 1, r, upd_ind, ind * 2 + 2);
    }
    max_index[ind] =
        values[max_index[ind * 2 + 1]] > values[max_index[ind * 2 + 2]]
            ? max_index[ind * 2 + 1]
            : max_index[ind * 2 + 2];
  }
};
struct operation {
  bool remove_edge;
  int v;
  int time;
  bool operator<(operation o1) const { return time < o1.time; }
};
struct edge {
  int v, to;
};
stack<operation> node_operations[MAXN];
vector<edge> edges;
pair<int, int> back_edges[MAXN];
bool removed_edges[MAXN];
bool visited_nodes[MAXN];
int real_numbers[MAXN];
int fake_numbers[MAXN];
int counter_ = 0;
int p_nodes[MAXN];
set<operation> operations[MAXN];
int get_parent(int v) {
  return p_nodes[v] == v ? v : p_nodes[v] = get_parent(p_nodes[v]);
}
void merge(int v, int to) {
  v = get_parent(v);
  to = get_parent(to);
  if (operations[v].size() < operations[v].size()) swap(v, to);
  for (auto d : operations[to]) {
    operations[v].insert(d);
  }
  p_nodes[to] = v;
}
void execute(int v1, int max_time) {
  real_numbers[counter_] = v1;
  fake_numbers[v1] = counter_;
  int v = counter_;
  p_nodes[counter_] = counter_;
  visited_nodes[v1] = true;
  while (!node_operations[v1].empty()) {
    operations[v].insert(node_operations[v1].top());
    node_operations[v1].pop();
  }
  counter_++;
  int start_index = counter_ - 1;
  while (operations[v].size() && (*operations[v].begin()).time < max_time) {
    v = get_parent(v);
    auto d = *operations[v].begin();
    operations[v].erase(d);
    if (!d.remove_edge)
      back_edges[d.time] = {start_index, counter_ - 1};
    else {
      int v1 = edges[d.v].to;
      int v2 = edges[d.v].v;
      if (visited_nodes[v1] && visited_nodes[v2]) continue;
      if (visited_nodes[v1]) swap(v1, v2);
      execute(v1, d.time);
      merge(v, fake_numbers[v1]);
    }
    v = get_parent(v);
  }
}
void solve() {
  int n, m, q;
  cin >> n >> m >> q;
  vector<int> node_m(n);
  for (int i = 0; i < n; ++i) {
    cin >> node_m[i];
    p_nodes[i] = i;
  }
  for (int i = 0; i < m; ++i) {
    int a, b;
    cin >> a >> b;
    edges.push_back({a - 1, b - 1});
  }
  vector<operation> operations;
  for (int i = 0; i < q; ++i) {
    string type;
    int pos;
    cin >> type >> pos;
    pos--;
    operations.push_back({type == "2", pos, n - i});
    if (type == "2") removed_edges[pos] = true;
  }
  for (int i = 0; i < m; ++i) {
    if (!removed_edges[i]) {
      operations.push_back({true, i, -i});
    }
  }
  for (auto u : operations) {
    if (!u.remove_edge) {
      node_operations[u.v].push(u);
    } else {
      int v1 = edges[u.v].to;
      int v2 = edges[u.v].v;
      node_operations[v1].push(u);
      node_operations[v2].push(u);
    }
  }
  for (int i = 0; i < n; ++i) {
    if (visited_nodes[i]) continue;
    execute(i, n + 1);
  }
  for (int i = 0; i < n; ++i) {
    values[i] = node_m[real_numbers[i]];
  }
  auto tree = new SegmentTree(n);
  for (auto v : operations) {
    if (v.remove_edge) continue;
    int ind1 = tree->get_max(0, n - 1, back_edges[v.time].first,
                             back_edges[v.time].second, 0);
    cout << values[ind1] << '\n';
    values[ind1] = 0;
    tree->update(0, n - 1, ind1, 0);
  }
}
int main() {
  solve();
  return 0;
}
