#include <bits/stdc++.h>   using namespace std;   template <class T>   inline T sqr(T x) {     return x * x;   }   const double EPS = 1e-9;   const int INF = 1000 * 1000 * 1000;   const long long LINF = INF * 1ll * INF;   const double DINF = 1e200;   const double PI = 3.1415926535897932384626433832795l;   int gcd(int a, int b) { return a ? gcd(b % a, a) : b; }   long long gcd(long long a, long long b) { return a ? gcd(b % a, a) : b; }   long long gcdex(long long a, long long b, long long &x, long long &y) {     if (!a) {       x = 0, y = 1;       return b;     }     long long k = b / a;     long long g = gcdex(b - k * a, a, y, x);     x -= k * y;     return g;   }   long long inv(long long a, long long m) {     assert(m > 1);     long long x, y, g;     g = gcdex(a, m, x, y);     return (x % (m / g) + m / g) % m / g;   }   long long crt(long long a1, long long m1, long long a2, long long m2) {     long long a = (a2 - a1 % m2 + m2) % m2;     long long x, y, g;     g = gcdex(m1, m2, x, y);     if (a % g) return -1;     long long m = m1 / g * m2;     assert(x + m2 >= 0);     x = a / g * (x + m2) % m2;     long long r = (a1 + x * m1) % m;     assert(r % m1 == a1 && r % m2 == a2);     return r;   }   long long powmod(long long a, long long p, long long m) {     assert(p >= 0);     long long r = 1;     while (p) {       if (p & 1) r = r * a % m;       p >>= 1;       a = a * a % m;     }     return r;   }   bool isprime(long long a) {     if (a <= 1) return false;     for (long long i = 2; i * i <= a; ++i) {       if (a % i == 0) return false;     }     return true;   }   long long sqrtup(long long a) {     if (!a) return 0;     long long x = max(0ll, (long long)sqrt((double)a));     while (x * x >= a) --x;     while ((x + 1) * (x + 1) < a) ++x;     return x + 1;   }   long long isqrt(long long a) {     if (a <= 0) {       assert(!a);       return 0;     }     long long x = (long long)sqrt((double)a);     while (sqr(x + 1) <= a) ++x;     while (x * x > a) --x;     return x;   }   long long sgn(long long x) { return x < 0 ? -1 : x > 0 ? 1 : 0; }   double randf() {     double m = RAND_MAX + 1.;     return (((rand() + .5) / m + rand()) / m + rand()) / m;   }   int rand30() {     assert(RAND_MAX >= (1 << 15) - 1);     return (         int)((((uint32_t)rand()) * (1u + (uint32_t)RAND_MAX) + (uint32_t)rand()) &              ((1u << 30) - 1));   }   template <class T>   void smin(T &a, T b) {     a = min(a, b);   }   template <class T>   void smax(T &a, T b) {     a = max(a, b);   }   template <class T>   ostream &operator<<(ostream &s, const vector<T> &v);   template <class A, class B>   ostream &operator<<(ostream &s, const pair<A, B> &p);   template <class K, class V>   ostream &operator<<(ostream &s, const map<K, V> &m);   template <class T>   ostream &operator<<(ostream &s, const set<T> &m);   template <class T, size_t N>   ostream &operator<<(ostream &s, const array<T, N> &a);   template <class... T>   ostream &operator<<(ostream &s, const tuple<T...> &t);   template <class T>   ostream &operator<<(ostream &s, const vector<T> &v) {     s <<  [ ;     for (int i = 0; i < (((int)(v).size())); ++i) {       if (i) s <<  , ;       s << v[i];     }     s <<  ] ;     return s;   }   template <class A, class B>   ostream &operator<<(ostream &s, const pair<A, B> &p) {     s <<  (  << p.first <<  ,  << p.second <<  ) ;     return s;   }   template <class K, class V>   ostream &operator<<(ostream &s, const map<K, V> &m) {     s <<  { ;     bool f = false;     for (const auto &it : m) {       if (f) s <<  , ;       f = true;       s << it.first <<  :   << it.second;     }     s <<  } ;     return s;   }   template <class T>   ostream &operator<<(ostream &s, const set<T> &m) {     s <<  { ;     bool f = false;     for (const auto &it : m) {       if (f) s <<  , ;       f = true;       s << it;     }     s <<  } ;     return s;   }   template <class T>   ostream &operator<<(ostream &s, const multiset<T> &m) {     s <<  { ;     bool f = false;     for (const auto &it : m) {       if (f) s <<  , ;       f = true;       s << it;     }     s <<  } ;     return s;   }   template <class T, class V, class C>   ostream &operator<<(ostream &s, const priority_queue<T, V, C> &q) {     auto a = q;     s <<  { ;     bool f = false;     while (!a.empty()) {       if (f) s <<  , ;       f = true;       s << a.top();       a.pop();     }     return s <<  } ;   }   template <class T, size_t N>   ostream &operator<<(ostream &s, const array<T, N> &a) {     s <<  [ ;     for (int i = 0; i < (((int)(a).size())); ++i) {       if (i) s <<  , ;       s << a[i];     }     s <<  ] ;     return s;   }   template <class T>   ostream &operator<<(ostream &s, const deque<T> &a) {     s <<  [ ;     for (int i = 0; i < (((int)(a).size())); ++i) {       if (i) s <<  , ;       s << a[i];     }     s <<  ] ;     return s;   }   template <size_t n, class... T>   struct put1 {     static ostream &put(ostream &s, const tuple<T...> &t) {       s << get<sizeof...(T) - n>(t);       if (n > 1) s <<  , ;       return put1<n - 1, T...>::put(s, t);     }   };   template <class... T>   struct put1<0, T...> {     static ostream &put(ostream &s, const tuple<T...> &t) { return s; }   };   template <class... T>   ostream &operator<<(ostream &s, const tuple<T...> &t) {     s <<  ( ;     put1<sizeof...(T), T...>::put(s, t);     s <<  ) ;     return s;   }   ostream &put3(ostream &s, const char *, bool) { return s; }   template <class U, class... T>   ostream &put3(ostream &s, const char *f, bool fs, U &&u, T &&...t) {     while (*f ==    ) ++f;     if (!fs) s <<  ,  ;     auto nf = f;     int d = 0;     while (*nf && (*nf !=  ,  || d)) {       if (*nf ==  ( )         ++d;       else if (*nf ==  ) )         --d;       ++nf;     }     auto nf2 = nf;     while (nf2 > f && *(nf2 - 1) ==    ) --nf;     fs = *f ==    ;     if (!fs) {       s.write(f, nf2 - f);       s <<  = ;     };     s << u;     if (fs) s <<    ;     if (*nf) ++nf;     return put3(s, nf, fs, forward<T>(t)...);   }   mt19937 mtrng;   struct comp {     vector<int> V;     vector<pair<int, int>> E;   };   struct tree {     vector<pair<int, int>> T;     tree(int n) : T(n * 4) {}     void init(int a, int b, int k, const vector<int> &A) {       if (b == a + 1) {         T[k] = make_pair(A[a], a);         return;       }       int c = (a + b) / 2;       init(a, c, k * 2 + 1, A);       init(c, b, k * 2 + 2, A);       T[k] = max(T[k * 2 + 1], T[k * 2 + 2]);     }     pair<int, int> getmax(int l, int r, int a, int b, int k) {       if (l >= b || r <= a) return make_pair(0, -1);       if (l <= a && r >= b) return T[k];       int c = (a + b) / 2;       return max(getmax(l, r, a, c, k * 2 + 1), getmax(l, r, c, b, k * 2 + 2));     }     void setv(int p, int v, int a, int b, int k) {       if (b == a + 1) {         T[k] = make_pair(v, p);         return;       }       int c = (a + b) / 2;       if (p < c)         setv(p, v, a, c, k * 2 + 1);       else         setv(p, v, c, b, k * 2 + 2);       T[k] = max(T[k * 2 + 1], T[k * 2 + 2]);     }   };   int main(int argc, char **argv) {     ios_base::sync_with_stdio(false);     cin.tie(0);     cout.precision(20);     srand(35964);     mtrng.seed(765674737);     int n, m, tc;     cin >> n >> m >> tc;     vector<int> P;     P.resize(n);     for (int i = 0; i < (n); ++i) cin >> P[i];     vector<pair<pair<int, int>, int>> E(m);     for (int i = 0; i < (m); ++i) {       cin >> E[i].first.first >> E[i].first.second;       --E[i].first.first;       --E[i].first.second;     }     vector<pair<int, int>> Q(tc);     for (int i = 0; i < (tc); ++i) {       cin >> Q[i].first >> Q[i].second;       --Q[i].second;       if (Q[i].first == 2) E[Q[i].second].second = 1;     }     vector<int> v2c(n);     vector<comp> cs(n);     for (int i = 0; i < (n); ++i) {       v2c[i] = i;       cs[i].V.push_back(i);     }     auto mer = [&](int a, int b, int q) {       if (a == b) return;       if (((int)(cs[a].V).size()) < ((int)(cs[b].V).size())) swap(a, b);       for (pair<int, int> x : cs[b].E)         cs[a].E.push_back(make_pair(x.first, x.second + ((int)(cs[a].V).size())));       if (q != -1) cs[a].E.push_back(make_pair(q, ((int)(cs[a].V).size())));       for (int v : cs[b].V) {         v2c[v] = a;         cs[a].V.push_back(v);       }       cs[b].V.clear();       cs[b].E.clear();     };     for (auto e : E) {       if (e.second) continue;       mer(v2c[e.first.first], v2c[e.first.second], -1);     }     for (int q = tc - 1; q >= 0; --q) {       if (Q[q].first != 2) continue;       pair<int, int> e = E[Q[q].second].first;       int a = v2c[e.first], b = v2c[e.second];       mer(a, b, q);     }     set<int> B;     vector<int> v2i(n);     vector<int> i2v;     vector<pair<int, int>> ev;     B.insert(0);     for (comp &c : cs) {       if (!((int)(c.V).size())) continue;       for (pair<int, int> e : c.E)         ev.push_back(make_pair(e.first, e.second + ((int)(i2v).size())));       for (int v : c.V) {         v2i[v] = ((int)(i2v).size());         i2v.push_back(v);       }       B.insert(((int)(i2v).size()));     }     assert(((int)(i2v).size()) == n);     sort((ev).begin(), (ev).end());     tree T(n);     vector<int> A(n);     for (int i = 0; i < (n); ++i) A[i] = P[i2v[i]];     T.init(0, n, 0, A);     int ei = 0;     for (int q = 0; q < (tc); ++q) {       if (Q[q].first == 1) {         int i = v2i[Q[q].second];         auto it = B.upper_bound(i);         int b = *it;         --it;         int a = *it;         pair<int, int> t = T.getmax(a, b, 0, n, 0);         T.setv(t.second, 0, 0, n, 0);         cout << t.first <<   n ;       } else if (ei < ((int)(ev).size()) && ev[ei].first == q) {         B.insert(ev[ei].second);         ++ei;       }     }     return 0;   }