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 maxN = 2e5, maxNN = 5e5, maxE = 3e5, maxQ = 5e5;
int n, m, q;
const int inf = maxNN + 1;
int p[maxN];
struct Edge {
  int u, v, done;
  void read() {
    scanf("%d %d", &u, &v), done = false;
    u--, v--;
  }
};
Edge edges[maxE];
struct Query {
  int type, value;
  void read() {
    scanf("%d %d", &type, &value);
    value--;
  }
};
Query queries[maxQ];
int parent[maxNN];
int root(int u) { return parent[u] < 0 ? u : parent[u] = root(parent[u]); }
vector<int> tree[maxNN];
void merge(int u, int v) {
  if ((u = root(u)) == (v = root(v))) return;
  parent[u] += parent[v];
  parent[v] = u;
  tree[u].push_back(v), tree[v].push_back(u);
}
void printNode(int u) {
  printf("%c%d", u < n ? 'v' : 'q', u < n ? u + 1 : u - n);
  if (u < n) printf("-%d", p[u]);
}
void printTree(int u = 0, int prv = -1, int depth = 0) {
  for (int i = 0; i < depth; i++) printf("   ");
  printNode(u);
  printf("\n");
  for (int v : tree[u])
    if (v != prv) printTree(v, u, depth + 1);
}
vector<int> roots;
bool visited[maxNN];
int findRoot(int u) {
  if (visited[u]) return maxNN;
  visited[u] = true;
  int root = u >= n ? u : maxNN;
  for (int v : tree[u]) root = min(root, findRoot(v));
  return root;
}
vector<vector<int>> eulerTours;
int myEulerTour[maxNN], in[maxNN], out[maxNN];
void buildEulerTour(int u, int prv = -1) {
  myEulerTour[u] = eulerTours.size() - 1;
  in[u] = eulerTours.back().size();
  eulerTours.back().push_back(u);
  for (int v : tree[u])
    if (v != prv) buildEulerTour(v, u);
  out[u] = eulerTours.back().size();
  eulerTours.back().push_back(u);
}
struct MinData {
  int value;
  MinData operator+(const MinData &other) {
    if (value < other.value) return *this;
    return other;
  }
};
const MinData minNil = MinData{inf};
struct MaxData {
  int value, vertex;
  MaxData operator+(const MaxData &other) {
    if (value > other.value) return *this;
    return other;
  }
};
const MaxData maxNil = MaxData{0};
template <class T>
struct Segtree {
  int size;
  T nil;
  vector<T> data;
  vector<T> st;
  Segtree() {}
  Segtree(int size, T nil) : size(size), nil(nil) {
    data.resize(size);
    st.resize(4 * size);
  }
  Segtree(vector<T> &data, T nil) : size(data.size()), data(data), nil(nil) {
    st.resize(4 * size);
    build();
  }
  void build() { build(1, 0, size - 1); }
  T query(int qlo, int qhi) { return query(qlo, qhi, 1, 0, size - 1); }
  void update(int pos, T value) { update(pos, value, 1, 0, size - 1); }
  void build(int i, int lo, int hi) {
    if (lo == hi) {
      st[i] = data[lo];
      return;
    }
    int mid = (lo + hi) >> 1;
    build(2 * i, lo, mid), build(2 * i + 1, mid + 1, hi);
    st[i] = st[2 * i] + st[2 * i + 1];
  }
  T query(int qlo, int qhi, int i, int lo, int hi) {
    if (hi < qlo || lo > qhi) return nil;
    if (lo >= qlo && hi <= qhi) return st[i];
    int mid = (lo + hi) >> 1;
    return query(qlo, qhi, 2 * i, lo, mid) +
           query(qlo, qhi, 2 * i + 1, mid + 1, hi);
  }
  void update(int pos, T &value, int i, int lo, int hi) {
    if (lo == hi) {
      st[i] = data[lo] = value;
      return;
    }
    int mid = (lo + hi) >> 1;
    if (pos <= mid)
      update(pos, value, 2 * i, lo, mid);
    else
      update(pos, value, 2 * i + 1, mid + 1, hi);
    st[i] = st[2 * i] + st[2 * i + 1];
  }
};
vector<Segtree<MaxData>> psegs;
vector<Segtree<MinData>> qsegs;
int main() {
  while (scanf("%d %d %d", &n, &m, &q) != EOF) {
    memset(parent, -1, sizeof(parent));
    for (int i = 0; i < maxNN; i++) tree[i].clear();
    for (int i = 0; i < n; i++) scanf("%d", &p[i]);
    for (int i = 0; i < m; i++) edges[i].read();
    for (int i = 0; i < q; i++) {
      queries[i].read();
      if (queries[i].type == 2) edges[queries[i].value].done = true;
    }
    for (int i = 0; i < m; i++)
      if (!edges[i].done) {
        Edge &e = edges[i];
        if (root(e.u) == root(e.v)) continue;
        merge(n + i, e.u), merge(n + i, e.v);
      }
    for (int i = q - 1; i >= 0; i--)
      if (queries[i].type == 2) {
        Edge &e = edges[queries[i].value];
        if (root(e.u) == root(e.v)) continue;
        merge(n + i, e.u), merge(n + i, e.v);
      }
    memset(visited, false, sizeof(visited));
    roots.clear();
    for (int i = 0; i < n; i++)
      if (!visited[i]) {
        int root = findRoot(i);
        roots.push_back(root == maxNN ? i : root);
      }
    eulerTours.clear(), psegs.clear(), qsegs.clear();
    for (int i = 0; i < roots.size(); i++) {
      eulerTours.push_back(vector<int>());
      buildEulerTour(roots[i]);
      psegs.push_back(Segtree<MaxData>(eulerTours.back().size(), maxNil));
      qsegs.push_back(Segtree<MinData>(eulerTours.back().size(), minNil));
      for (int j = 0; j < eulerTours.back().size(); j++) {
        int u = eulerTours.back()[j];
        psegs.back().data[j].value = u < n ? p[u] : -1;
        psegs.back().data[j].vertex = u < n ? u : -1;
        qsegs.back().data[j].value = u >= n && out[u] == j ? u : inf;
      }
      psegs.back().build();
      qsegs.back().build();
    }
    if (0) {
      for (int i = 0; i < roots.size(); i++) {
        printTree(roots[i]);
        printf("--------\n");
      }
      for (int i = 0; i < eulerTours.size(); i++) {
        for (int u : eulerTours[i]) {
          printNode(u);
          printf(" ");
        }
        printf("\n-----\n");
      }
    }
    for (int i = 0; i < q; i++)
      if (queries[i].type == 1) {
        int u = queries[i].value, met = myEulerTour[u];
        if (0) printf("\tquery %d %d >= %d\n", u + 1, met, i + 1);
        int highestQuery =
            qsegs[met].query(out[u], eulerTours[met].size() - 1).value;
        int lo = in[u], hi = out[u];
        if (highestQuery != inf) lo = in[highestQuery], hi = out[highestQuery];
        if (lo > in[u]) lo = in[u], hi = out[u];
        if (0) printf("\t\thighestQuery: %d\n", highestQuery - n);
        MaxData ans = psegs[met].query(lo, hi);
        printf("%d\n", ans.value);
        psegs[met].update(in[ans.vertex], maxNil);
        psegs[met].update(out[ans.vertex], maxNil);
      } else {
        int u = i + n;
        qsegs[myEulerTour[u]].update(out[u], minNil);
      }
  }
  return 0;
}
