#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1.0);
namespace IO {
bool REOF = 1;
inline char nc() {
  static char buf[1 << 20], *p1 = buf, *p2 = buf;
  return p1 == p2 && REOF &&
                 (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2)
             ? (REOF = 0, EOF)
             : *p1++;
}
template <typename T>
inline bool read(T &x) {
  char c = nc();
  bool f = 0;
  x = 0;
  while (c < '0' || c > '9') c == '-' && (f = 1), c = nc();
  while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = nc();
  if (f) x = -x;
  return REOF;
}
template <typename T>
inline void write(T x) {
  if (x > 9) write(x / 10);
  putchar('0' + x % 10);
}
template <typename T, typename... T2>
inline bool read(T &x, T2 &...rest) {
  read(x);
  return read(rest...);
}
inline bool isdowncase(char c) { return (c >= 'a') && (c <= 'z'); }
inline bool isupcase(char c) { return (c >= 'A') && (c <= 'Z'); }
inline bool isdigit(char c) { return (c >= '0') && (c <= '9'); }
inline bool need(char &c) { return isdowncase(c) || isupcase(c) || isdigit(c); }
inline bool read_str(char *a) {
  while ((*a = nc()) && need(*a) && REOF) ++a;
  *a = '\0';
  return REOF;
}
inline bool read_db(double &x) {
  bool f = 0;
  char ch = nc();
  x = 0;
  while (ch < '0' || ch > '9') {
    f |= (ch == '-');
    ch = nc();
  }
  while (ch >= '0' && ch <= '9') {
    x = x * 10.0 + (ch ^ 48);
    ch = nc();
  }
  if (ch == '.') {
    double temp = 1;
    ch = nc();
    while (ch >= '0' && ch <= '9') {
      temp = temp / 10.0;
      x = x + temp * (ch ^ 48);
      ch = nc();
    }
  }
  if (f) x = -x;
  return REOF;
}
template <typename TH>
inline void _dbg(const char *sdbg, TH h) {
  cerr << sdbg << '=' << h << endl;
}
template <typename TH, typename... TA>
inline void _dbg(const char *sdbg, TH h, TA... a) {
  while (*sdbg != ',') cerr << *sdbg++;
  cerr << '=' << h << ',' << ' ';
  _dbg(sdbg + 1, a...);
}
template <typename T>
ostream &operator<<(ostream &os, vector<T> V) {
  os << "[ ";
  for (auto vv : V) os << vv << ",";
  return os << " ]";
}
template <typename T>
ostream &operator<<(ostream &os, set<T> V) {
  os << "[ ";
  for (auto vv : V) os << vv << ",";
  return os << " ]";
}
template <typename T>
ostream &operator<<(ostream &os, multiset<T> V) {
  os << "[ ";
  for (auto vv : V) os << vv << ",";
  return os << " ]";
}
template <typename T>
ostream &operator<<(ostream &os, map<T, T> V) {
  os << "[ ";
  for (auto vv : V) os << vv << ",";
  return os << " ]";
}
template <typename L, typename R>
ostream &operator<<(ostream &os, pair<L, R> P) {
  return os << "(" << P.first << "," << P.second << ")";
}
template <typename TH>
TH MIN(TH a, TH b) {
  return min(a, b);
}
template <typename TH, typename... TA>
TH MIN(TH a, TA... c) {
  return min(a, MIN(c...));
}
template <typename TH>
TH MAX(TH a, TH b) {
  return max(a, b);
}
template <typename TH, typename... TA>
TH MAX(TH a, TA... c) {
  return max(a, MIN(c...));
}
template <typename T>
void updMin(T &a, T b) {
  if (a > b) a = b;
}
template <typename T>
void updMax(T &a, T b) {
  if (a < b) a = b;
}
}  // namespace IO
using namespace IO;
const int N = 5e5 + 5;
const int M = 5e5 + 5;
const int V = 5e7 + 5;
const long long MOD = 998244353;
const int INF = 0x3f3f3f3f;
const long long LLINF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-8;
vector<int> G[N];
int n, m, q, p[N], is[N];
pair<int, int> query[N], e[N];
int fa[N];
int find(int x) { return x == fa[x] ? x : (fa[x] = find(fa[x])); }
void merge(int x, int y) {
  x = find(x);
  y = find(y);
  if (x == y) return;
  ++n;
  fa[n] = n;
  fa[x] = n;
  fa[y] = n;
  G[n].push_back(x);
  G[n].push_back(y);
}
pair<int, int> ma[N << 2];
pair<int, int> queryMax(int x, int l, int r, int L, int R) {
  if (L > R || l > R || r < L) return pair<int, int>(0, 0);
  if (l == L && r == R) return ma[x];
  int mid = (l + r) >> 1;
  if (R <= mid)
    return queryMax(x << 1, l, mid, L, R);
  else if (L > mid)
    return queryMax(x << 1 | 1, mid + 1, r, L, R);
  return max(queryMax(x << 1, l, mid, L, mid),
             queryMax(x << 1 | 1, mid + 1, r, mid + 1, R));
}
void updatePosition(int x, int l, int r, int pos, pair<int, int> val) {
  if (l == r) {
    ma[x] = val;
    return;
  }
  int mid = (l + r) >> 1;
  if (pos <= mid)
    updatePosition(x << 1, l, mid, pos, val);
  else
    updatePosition(x << 1 | 1, mid + 1, r, pos, val);
  ma[x] = max(ma[x << 1], ma[x << 1 | 1]);
}
int dfs_clock, st[N], ed[N];
void dfs(int u) {
  st[u] = ++dfs_clock;
  for (int v : G[u]) {
    dfs(v);
  }
  ed[u] = dfs_clock;
}
void solve(int Case) {
  read(n, m, q);
  for (int i = (1); i <= (n); ++i) read(p[i]);
  int u, v;
  for (int i = (1); i <= (m); ++i) {
    read(u, v);
    e[i] = pair<int, int>(u, v);
  }
  int op;
  for (int i = (1); i <= (q); ++i) {
    read(op, v);
    query[i] = pair<int, int>(op, v);
    if (op == 2) is[v] = 1;
  }
  for (int i = (1); i <= (n); ++i) fa[i] = i;
  for (int i = (1); i <= (m); ++i)
    if (!is[i]) {
      merge(e[i].first, e[i].second);
    }
  for (int i = (q); i >= (1); --i) {
    if (query[i].first == 1) {
      query[i].second = find(query[i].second);
    } else {
      int eid = query[i].second;
      merge(e[eid].first, e[eid].second);
    }
  }
  for (int i = (1); i <= (n); ++i)
    if (find(i) == i) {
      dfs(i);
    }
  for (int i = (1); i <= (n); ++i) {
    updatePosition(1, 1, n, st[i], pair<int, int>(p[i], st[i]));
  }
  for (int i = (1); i <= (q); ++i)
    if (query[i].first == 1) {
      int id = query[i].second;
      pair<int, int> ans = queryMax(1, 1, n, st[id], ed[id]);
      printf("%d\n", ans.first);
      if (ans.first != 0)
        updatePosition(1, 1, n, ans.second, pair<int, int>(0, 0));
    }
}
int main() {
  int T = 1;
  for (int _ = 1; _ <= T; _++) solve(_);
  return 0;
}
