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;
struct union_find {
  vector<int> p;
  union_find(int n) : p(n, -1) {}
  bool join(int u, int v) {
    if ((u = root(u)) == (v = root(v))) return false;
    if (p[u] > p[v]) swap(u, v);
    p[u] += p[v];
    p[v] = u;
    return true;
  }
  int root(int u) { return p[u] < 0 ? u : p[u] = root(p[u]); }
  int size(int u) { return -p[root(u)]; }
};
template <class node>
struct link_cut_tree {
  bool connected(node* u, node* v) { return lca(u, v) != NULL; }
  int depth(node* u) {
    access(u);
    return get_sz(u->ch[0]);
  }
  node* get_root(node* u) {
    access(u);
    while (u->ch[0]) u = u->ch[0], u->push();
    return access(u), u;
  }
  node* ancestor(node* u, int k) {
    k = depth(u) - k;
    assert(k >= 0);
    for (;; u->push()) {
      int sz = get_sz(u->ch[0]);
      if (sz == k) return access(u), u;
      if (sz < k)
        k -= sz + 1, u = u->ch[1];
      else
        u = u->ch[0];
    }
    assert(0);
  }
  node* lca(node* u, node* v) {
    if (u == v) return u;
    access(u);
    access(v);
    if (!u->p) return NULL;
    u->splay();
    return u->p ?: u;
  }
  void link(node* u, node* v) {
    assert(!connected(u, v));
    make_root(v);
    access(u);
    set_link(v, u, 0);
    v->update();
  }
  void cut(node* u) {
    access(u);
    u->ch[0]->p = NULL;
    u->ch[0] = NULL;
    u->update();
  }
  void cut(node* u, node* v) { cut(depth(u) > depth(v) ? u : v); }
  void make_root(node* u) {
    access(u);
    u->reverse();
    access(u);
    assert(!u->ch[0] && !u->ch[1]);
  }
  void access(node* u) {
    for (node *v = u, *pre = NULL; v; v = v->p) {
      v->splay();
      if (pre) v->update_vsub(pre, false);
      if (v->ch[1]) v->update_vsub(v->ch[1], true);
      v->ch[1] = pre;
      v->update();
      pre = v;
    }
    u->splay();
    assert(!u->ch[1]);
  }
  node* operator[](int i) { return &data[i]; }
  int operator[](node* i) { return i - &data[0]; }
  vector<node> data;
  link_cut_tree(int n) : data(n) {}
};
template <typename pnode>
struct splay_tree {
  pnode ch[2], p;
  splay_tree() { ch[0] = ch[1] = p = NULL; }
  int dir() {
    if (!p) return -2;
    if (p->ch[0] == this) return 0;
    if (p->ch[1] == this) return 1;
    return -1;
  }
  bool is_root() { return dir() < 0; }
  friend void set_link(pnode u, pnode v, int d) {
    if (v) v->p = u;
    if (d >= 0) u->ch[d] = v;
  }
  void rotate() {
    assert(!is_root());
    int x = dir();
    pnode g = p;
    set_link(g->p, static_cast<pnode>(this), g->dir());
    set_link(g, ch[x ^ 1], x);
    set_link(static_cast<pnode>(this), g, x ^ 1);
    g->update();
  }
  void splay() {
    const pnode& self = static_cast<pnode>(this);
    while (!is_root() && !p->is_root()) {
      p->p->push(), p->push(), self->push();
      dir() == p->dir() ? p->rotate() : self->rotate();
      self->rotate();
    }
    if (!is_root()) p->push(), self->push(), self->rotate();
    self->push();
    self->update();
  }
};
template <typename pnode, class splay_tree_vchs>
struct splay_tree_lct : splay_tree<pnode> {
  splay_tree_vchs vnode;
  using splay_tree<pnode>::ch;
  bool rev;
  int sz;
  splay_tree_vchs* root;
  splay_tree_lct() : splay_tree<pnode>() {
    root = NULL;
    rev = 0;
    sz = 1;
  }
  friend int get_sz(pnode u) { return u ? u->sz : 0; }
  void update() { sz = 1 + get_sz(ch[0]) + get_sz(ch[1]); }
  void push() {
    if (rev) {
      if (ch[0]) ch[0]->reverse();
      if (ch[1]) ch[1]->reverse();
      rev = 0;
    }
  }
  void rotate() {
    swap(vnode, this->p->vnode);
    splay_tree<pnode>::rotate();
  }
  void splay() {
    auto v = &vnode;
    bool r = !v->key;
    splay_tree<pnode>::splay();
    if (r && v->key) {
      if (this->p->root->key == NULL) this->p->root = v;
      if (v->p) v->p->ch[v->p->ch[1] == &v->key->vnode] = v;
      if (v->ch[0]) v->ch[0]->p = v;
      if (v->ch[1]) v->ch[1]->p = v;
      v->key = static_cast<pnode>(this);
    }
  }
  void reverse() {
    rev ^= 1;
    swap(ch[0], ch[1]);
  }
  void update_vsub(pnode v, bool add) {
    auto& u = root;
    if (add) {
      v->vnode = splay_tree_vchs(v);
      if (!u) {
        u = &v->vnode;
        return;
      }
      u->push();
      while (u->ch[1]) u = u->ch[1], u->push();
      u->ch[1] = &v->vnode;
      u->ch[1]->p = u;
      u = u->ch[1];
      u->splay();
    } else {
      auto x = &v->vnode;
      x->splay();
      if (!x->ch[0]) {
        u = x->ch[1];
      } else if (!x->ch[1]) {
        u = x->ch[0];
      } else {
        u = x->ch[0];
        u->p = NULL;
        u->push();
        while (u->ch[1]) u = u->ch[1], u->push();
        u->ch[1] = x->ch[1];
        x->ch[1]->p = u;
        u->splay();
      }
      if (u) u->p = NULL;
      x->key = NULL;
    }
  }
};
template <typename pnode>
struct splay_tree_vchs : splay_tree<splay_tree_vchs<pnode>*> {
  using splay_tree<splay_tree_vchs<pnode>*>::ch;
  pnode key;
  int sub;
  splay_tree_vchs() : key(NULL){};
  splay_tree_vchs(const pnode& key)
      : splay_tree<splay_tree_vchs<pnode>*>(), key(key) {
    build();
  }
  void build() { sub = key->sub; }
  void update() {
    build();
    if (ch[0]) sub = max(sub, ch[0]->sub);
    if (ch[1]) sub = max(sub, ch[1]->sub);
  }
  void push() {}
};
struct node : splay_tree_lct<node*, splay_tree_vchs<node*>> {
  int x, sub;
  node() : splay_tree_lct() { x = sub = 0; }
  void update() {
    splay_tree_lct::update();
    sub = x;
    if (root) sub = max(x, root->sub);
    if (ch[0]) sub = max(sub, ch[0]->sub);
    if (ch[1]) sub = max(sub, ch[1]->sub);
  }
  void push() { splay_tree_lct::push(); }
  void reverse() { splay_tree_lct::reverse(); }
};
int main() {
  ios_base::sync_with_stdio(0), cin.tie(0);
  int n, m, q;
  cin >> n >> m >> q;
  vector<int> p(n), who(n + 1);
  link_cut_tree<node> lct(n);
  for (auto& i : p) {
    int u = &i - &p[0];
    cin >> i;
    who[i] = u;
    lct[u]->x = lct[u]->sub = i;
  }
  vector<pair<int, int>> edges(m);
  for (auto& i : edges) cin >> i.first >> i.second, --i.first, --i.second;
  vector<pair<int, int>> prio(m);
  for (int i = 0; i < m; ++i) prio[i] = {q + 1, i};
  vector<pair<int, int>> queries(q);
  for (auto& i : queries) {
    cin >> i.first >> i.second, --i.second;
    if (i.first == 2) prio[i.second].first = &i - &queries[0];
  }
  vector<bool> alive(m);
  union_find uf(n);
  sort(prio.rbegin(), prio.rend());
  for (auto i : prio) {
    int u, v;
    tie(u, v) = edges[i.second];
    if (uf.join(u, v)) {
      alive[i.second] = true;
      lct.link(lct[u], lct[v]);
    }
  }
  for (auto que : queries) {
    if (que.first == 1) {
      auto u = lct[que.second];
      lct.access(u);
      cout << u->sub << "\n";
      if (u->sub != 0) {
        auto v = lct[who[u->sub]];
        lct.access(v);
        v->x = 0;
        v->update();
      }
    } else if (alive[que.second]) {
      int u, v;
      tie(u, v) = edges[que.second];
      lct.cut(lct[u], lct[v]);
    }
  }
  return 0;
}
