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 oo = (int)1e9;
struct NodeP {
  int val;
  NodeP *left, *right;
  NodeP() {}
  NodeP(int v) { val = v; }
};
struct Range {
  int L, R;
  Range() {}
  Range(int a, int b) {
    L = a;
    R = b;
  }
  bool operator<(const Range& r) const { return R < r.R; }
};
struct Event {
  bool isValid = false;
  Range original, split1, split2;
  Event() {}
  Event(Range a, Range b, Range c) {
    isValid = true;
    original = a;
    split1 = b, split2 = c;
  }
};
struct ST {
  struct Node {
    int L, R;
    pair<int, int> maxVal;
    Node() {}
    Node(int a, int b) {
      L = a;
      R = b;
      maxVal = {0, L};
    }
  };
  vector<Node> st;
  ST(int n) {
    st.resize(4 * n + 10, Node());
    init(1, 0, n - 1);
  }
  void init(int p, int a, int b) {
    st[p] = Node(a, b);
    if (a == b) return;
    int mid = (a + b) / 2;
    init(2 * p, a, mid);
    init(2 * p + 1, mid + 1, b);
  }
  void pointUpdate(int p, int pos, long long int val) {
    Node& now = st[p];
    if (pos < now.L || now.R < pos) return;
    if (pos <= now.L && now.R <= pos) {
      st[p].maxVal.first = val;
      return;
    }
    pointUpdate(2 * p, pos, val);
    pointUpdate(2 * p + 1, pos, val);
    update(p);
  }
  pair<int, int> rangeMax(int p, int a, int b) {
    Node& now = st[p];
    if (b < now.L || now.R < a) return {-oo, -1};
    if (a <= now.L && now.R <= b) {
      return st[p].maxVal;
    }
    auto ret1 = rangeMax(2 * p, a, b);
    auto ret2 = rangeMax(2 * p + 1, a, b);
    update(p);
    return max(ret1, ret2);
  }
  void update(int p) {
    Node& now = st[p];
    now.maxVal = max(st[2 * p].maxVal, st[2 * p + 1].maxVal);
  }
};
vector<int> lefts, rights, leftHead, rightHead;
vector<int> par;
int find(int i) {
  if (par[i] == i) return i;
  return par[i] = find(par[i]);
}
bool merge(int u, int v) {
  u = find(u), v = find(v);
  if (u == v) return false;
  par[v] = u;
  int rHead = rightHead[u], lHead = leftHead[v];
  rights[rHead] = lHead;
  lefts[lHead] = rHead;
  rightHead[u] = rightHead[v];
  return true;
}
void sol() {
  int n, m, q;
  cin >> n >> m >> q;
  vector<int> vals(n);
  for (int& x : vals) cin >> x;
  vector<pair<int, int>> queries(q), edges(m);
  for (int i = 0; i < m; i++) {
    int x, y;
    cin >> x >> y;
    x--;
    y--;
    edges[i] = {x, y};
  }
  vector<bool> edgesRem(m);
  for (int i = 0; i < q; i++) {
    int type, node;
    cin >> type >> node;
    node--;
    queries[i] = {type, node};
    if (type == 2) edgesRem[node] = true;
  }
  for (int i = 0; i < m; i++)
    if (!edgesRem[i]) {
      queries.push_back({2, i});
    }
  par = vector<int>(n);
  lefts = rights = leftHead = rightHead = vector<int>(n);
  auto clearDSU = [&] {
    for (int i = 0; i < n; i++) {
      par[i] = i;
      leftHead[i] = rightHead[i] = i;
      lefts[i] = rights[i] = i;
    }
  };
  clearDSU();
  for (int i = (int)queries.size() - 1; i >= 0; i--) {
    auto now = queries[i];
    if (now.first != 2) continue;
    auto edge = edges[now.second];
    merge(edge.first, edge.second);
  }
  vector<int> arr(n);
  int ptr = 0;
  set<Range> curRanges;
  for (int i = 0; i < n; i++)
    if (find(i) == i) {
      int now = lefts[i];
      int oPtr = ptr;
      while (true) {
        arr[ptr++] = now;
        if (rights[now] == now) break;
        now = rights[now];
      }
      curRanges.insert(Range(oPtr, ptr - 1));
    }
  vector<int> pos(n);
  for (int i = 0; i < n; i++) pos[arr[i]] = i;
  auto makeRange = [&](int u) {
    int L = leftHead[u], R = rightHead[u];
    if (pos[L] > pos[R]) swap(L, R);
    return Range(pos[L], pos[R]);
  };
  clearDSU();
  vector<Event> events((int)queries.size());
  for (int i = (int)queries.size() - 1; i >= 0; i--) {
    auto now = queries[i];
    if (now.first != 2) continue;
    auto edge = edges[now.second];
    int u = find(edge.first), v = find(edge.second);
    if (u != v) {
      par[v] = u;
      int rHead = rightHead[u], lHead = leftHead[v];
      Range old1 = makeRange(u), old2 = makeRange(v);
      rights[rHead] = lHead;
      lefts[lHead] = rHead;
      rightHead[u] = rightHead[v];
      Range new1 = makeRange(u);
      events[i] = Event(new1, old1, old2);
    }
  }
  ST st = ST(n);
  for (int i = 0; i < n; i++) {
    st.pointUpdate(1, pos[i], vals[i]);
  }
  for (int i = 0; i < q; i++) {
    auto now = queries[i];
    if (now.first == 1) {
      int spot = pos[now.second];
      auto who = curRanges.lower_bound(Range(spot, spot));
      auto range = *who;
      auto ans = st.rangeMax(1, range.L, range.R);
      cout << ans.first << '\n';
      st.pointUpdate(1, ans.second, 0);
    } else {
      if (events[i].isValid) {
        curRanges.erase(events[i].original);
        curRanges.insert(events[i].split1);
        curRanges.insert(events[i].split2);
      }
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  sol();
  return 0;
}
