#include <bits/stdc++.h>
#pragma GCC optimize("O3", "unroll-all-loops")
#pragma GCC target("sse4.2")
using namespace std;
ifstream in;
ofstream out;
const long long kk = 1000;
const long long ml = kk * kk;
const long long mod = ml * kk + 7;
const long long inf = ml * ml * ml + 7;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
struct Tree {
  int s = 1;
  int n = 0;
  long long my_null = -mod;
  vector<pair<long long, long long>> t;
  vector<pair<long long, long long>> seg;
  inline long long res(long long v1, long long v2) { return max(v1, v2); }
  void cnt_seg() {
    seg.resize(2 * s);
    seg[1] = {0, s};
    for (int i = 1; i < s; i++) {
      int tm = seg[i].first + seg[i].second >> 1;
      seg[2 * i] = {seg[i].first, tm};
      seg[2 * i + 1] = {tm, seg[i].second};
    }
  }
  void build(long long sz) {
    n = sz;
    while (s < n) s <<= 1;
    t.resize(2 * s, {my_null, 0});
    cnt_seg();
  }
  void build(vector<int> v) {
    n = v.size();
    while (s < n) s <<= 1;
    t.resize(2 * s, {my_null, 0});
    for (int i = 0; i < n; i++) t[s + i] = {v[i], 0};
    for (int i = s - 1; i > 0; i--) upd(i);
    cnt_seg();
  }
  inline void adder(int v, long long val) {
    t[v].first += val;
    t[v].second += val;
  }
  void upd(int v) {
    if (v >= s) return;
    t[v].first = res(t[2 * v].first, t[2 * v + 1].first);
  }
  void push(int v) {
    if (v >= s) return;
    long long psh = t[v].second;
    if (psh == 0) return;
    t[v].second = 0;
    adder(2 * v, psh);
    adder(2 * v + 1, psh);
  }
  long long val(int l, int r, int v, int tl, int tr) {
    if (r <= tl || tr <= l) return my_null;
    push(v);
    if (l <= tl && tr <= r) return t[v].first;
    int tm = tl + tr >> 1;
    long long v1 = val(l, r, 2 * v, tl, tm);
    long long v2 = val(l, r, 2 * v + 1, tm, tr);
    upd(v);
    return res(v1, v2);
  }
  long long val(int l, int r) { return val(l, r + 1, 1, 0, s); }
  long long val(int pl) { return val(pl, pl + 1, 1, 0, s); }
  void add(int l, int r, int v, int tl, int tr, long long val) {
    if (r <= tl || tr <= l) return;
    push(v);
    if (l <= tl && tr <= r) return void(adder(v, val));
    int tm = tl + tr >> 1;
    add(l, r, 2 * v, tl, tm, val);
    add(l, r, 2 * v + 1, tm, tr, val);
    upd(v);
  }
  void add(int v, long long val) {
    v += s;
    t[v].first += val;
    v >>= 1;
    while (v) upd(v), v >>= 1;
  }
  void add(int l, int r, long long t) { add(l, r + 1, 1, 0, s, t); }
  void show() {
    for (long long i = 1; i < 2 * s; i++) {
      cout << '\t' << '{' << t[i].first << "   " << t[i].second << "} ";
      if ((i & (i + 1)) == 0) cout << endl;
    }
  }
};
int n, m, q;
vector<int> val;
vector<int> ver_by_val;
vector<vector<int>> e;
vector<pair<int, int>> all;
vector<pair<int, int>> qr;
bool viv = false;
vector<int> p;
vector<vector<int>> kids;
int nxt;
vector<int> spliter;
vector<int> value_st;
Tree st;
set<pair<int, int>> seg;
void read() {
  cin >> n >> m >> q;
  val.resize(n);
  ver_by_val.resize(n);
  for (auto &i : val) cin >> i, i--;
  for (int i = 0; i < n; i++) ver_by_val[val[i]] = i;
  e.resize(n);
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    e[a].push_back(b);
    e[b].push_back(a);
    all.push_back({a, b});
  }
  qr.resize(q);
  set<int> left;
  for (int i = 0; i < m; i++) left.insert(i);
  for (auto &p : qr) {
    cin >> p.first >> p.second;
    p.first--;
    p.second--;
    if (p.first) left.erase(p.second);
  }
  for (auto ed : left) qr.push_back({1, ed});
  q = qr.size();
}
int pr(int v) {
  if (p[v] == v) return v;
  return p[v] = pr(p[v]);
}
bool unit(int v, int u) {
  v = pr(v);
  u = pr(u);
  if (v == u) return false;
  int s = nxt++;
  kids[s].push_back(v);
  kids[s].push_back(u);
  p[v] = s;
  p[u] = s;
  return true;
}
void prepare() {
  p.resize(2 * n - 1);
  kids.resize(2 * n - 1);
  for (int i = 0; i < p.size(); i++) p[i] = i;
  nxt = n;
  vector<long long> ord;
  for (auto p : qr)
    if (p.first) ord.push_back(p.second);
  reverse(ord.begin(), ord.end());
  for (auto num : ord) {
    int v = all[num].first;
    int u = all[num].second;
    if (unit(v, u))
      spliter.push_back(nxt - 1);
    else
      spliter.push_back(-1);
  }
  if (viv) {
    for (int i = 0; i < nxt; i++) {
      cout << "kids[" << i << "] = ";
      for (auto v : kids[i]) cout << v << ' ';
      cout << endl;
    }
    cout << "Spliter = ";
    for (auto i : spliter) cout << i << ' ';
    cout << endl;
  }
}
vector<int> tin, tout;
int t = 0;
void DFS(int v) {
  int my_val = -mod;
  if (v < n) my_val = val[v];
  value_st[t] = my_val;
  tin[v] = t++;
  for (auto u : kids[v])
    if (tin[u] == -1) DFS(u);
  value_st[t] = my_val;
  tout[v] = t++;
}
void build() {
  tin.resize(nxt, -1);
  tout.resize(nxt, -1);
  value_st.resize(2 * nxt);
  for (int i = nxt - 1; i >= 0; i--) {
    if (tin[i] == -1) {
      DFS(i);
      seg.insert({tin[i], tout[i]});
    }
  }
  st.build(value_st);
  if (viv) {
    for (int i = 0; i < nxt; i++) {
      cout << "seg[" << i << "] = " << tin[i] << ' ' << tout[i] << endl;
    }
  }
}
bool out_seg(int p, pair<int, int> seg) {
  if (p < seg.first || seg.second < p) return true;
  return false;
}
void work() {
  if (viv) st.show();
  for (auto p : qr) {
    if (p.first) {
      int s = spliter.back();
      spliter.pop_back();
      if (s != -1) {
        int v = kids[s][0];
        int u = kids[s][1];
        if (viv) {
          cout << "split vertex " << s << " on " << v << " and " << u << endl;
        }
        seg.erase({tin[s], tout[s]});
        seg.insert({tin[v], tout[v]});
        seg.insert({tin[u], tout[u]});
        if (viv) {
          for (auto p : seg)
            cout << '{' << p.first << ", " << p.second << "}, ";
          cout << endl;
        }
      }
    } else {
      int v = p.second;
      int pl = tin[v];
      if (viv) cout << "find for " << v << " include " << tin[v] << endl;
      auto z = seg.lower_bound({pl, pl});
      while (out_seg(pl, *z)) z--;
      auto pr = *z;
      int l = pr.first;
      int r = pr.second;
      auto ans = st.val(l, r);
      if (ans >= 0) {
        cout << ans + 1 << '\n';
        v = ver_by_val[ans];
        st.add(tin[v], tin[v], -mod);
        st.add(tout[v], tout[v], -mod);
        if (viv) st.show();
      } else {
        cout << "0\n";
      }
    }
  }
}
void solve() {
  read();
  prepare();
  build();
  work();
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long t = 1;
  while (t--) solve();
  return 0;
}

### Prompt

Your task is to create a Cpp solution to the following problem:

You are given an undirected graph consisting of n vertices and m edges. Initially there is a single integer written on every vertex: the vertex i has p_i written on it. All p_i are distinct integers from 1 to n.

You have to process q queries of two types:

  * 1 v — among all vertices reachable from the vertex v using the edges of the graph (including the vertex v itself), find a vertex u with the largest number p_u written on it, print p_u and replace p_u with 0; 
  * 2 i — delete the i-th edge from the graph. 



Note that, in a query of the first type, it is possible that all vertices reachable from v have 0 written on them. In this case, u is not explicitly defined, but since the selection of u does not affect anything, you can choose any vertex reachable from v and print its value (which is 0). 

Input

The first line contains three integers n, m and q (1 ≤ n ≤ 2 ⋅ 10^5; 1 ≤ m ≤ 3 ⋅ 10^5; 1 ≤ q ≤ 5 ⋅ 10^5).

The second line contains n distinct integers p_1, p_2, ..., p_n, where p_i is the number initially written on vertex i (1 ≤ p_i ≤ n).

Then m lines follow, the i-th of them contains two integers a_i and b_i (1 ≤ a_i, b_i ≤ n, a_i ≠ b_i) and means that the i-th edge connects vertices a_i and b_i. It is guaranteed that the graph does not contain multi-edges.

Then q lines follow, which describe the queries. Each line is given by one of the following formats:

  * 1 v — denotes a query of the first type with a vertex v (1 ≤ v ≤ n). 
  * 2 i — denotes a query of the second type with an edge i (1 ≤ i ≤ m). For each query of the second type, it is guaranteed that the corresponding edge is not deleted from the graph yet. 

Output

For every query of the first type, print the value of p_u written on the chosen vertex u.

Example

Input


5 4 6
1 2 5 4 3
1 2
2 3
1 3
4 5
1 1
2 1
2 3
1 1
1 2
1 2


Output


5
1
2
0

### Response

```cpp
#include <bits/stdc++.h>
#pragma GCC optimize("O3", "unroll-all-loops")
#pragma GCC target("sse4.2")
using namespace std;
ifstream in;
ofstream out;
const long long kk = 1000;
const long long ml = kk * kk;
const long long mod = ml * kk + 7;
const long long inf = ml * ml * ml + 7;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
struct Tree {
  int s = 1;
  int n = 0;
  long long my_null = -mod;
  vector<pair<long long, long long>> t;
  vector<pair<long long, long long>> seg;
  inline long long res(long long v1, long long v2) { return max(v1, v2); }
  void cnt_seg() {
    seg.resize(2 * s);
    seg[1] = {0, s};
    for (int i = 1; i < s; i++) {
      int tm = seg[i].first + seg[i].second >> 1;
      seg[2 * i] = {seg[i].first, tm};
      seg[2 * i + 1] = {tm, seg[i].second};
    }
  }
  void build(long long sz) {
    n = sz;
    while (s < n) s <<= 1;
    t.resize(2 * s, {my_null, 0});
    cnt_seg();
  }
  void build(vector<int> v) {
    n = v.size();
    while (s < n) s <<= 1;
    t.resize(2 * s, {my_null, 0});
    for (int i = 0; i < n; i++) t[s + i] = {v[i], 0};
    for (int i = s - 1; i > 0; i--) upd(i);
    cnt_seg();
  }
  inline void adder(int v, long long val) {
    t[v].first += val;
    t[v].second += val;
  }
  void upd(int v) {
    if (v >= s) return;
    t[v].first = res(t[2 * v].first, t[2 * v + 1].first);
  }
  void push(int v) {
    if (v >= s) return;
    long long psh = t[v].second;
    if (psh == 0) return;
    t[v].second = 0;
    adder(2 * v, psh);
    adder(2 * v + 1, psh);
  }
  long long val(int l, int r, int v, int tl, int tr) {
    if (r <= tl || tr <= l) return my_null;
    push(v);
    if (l <= tl && tr <= r) return t[v].first;
    int tm = tl + tr >> 1;
    long long v1 = val(l, r, 2 * v, tl, tm);
    long long v2 = val(l, r, 2 * v + 1, tm, tr);
    upd(v);
    return res(v1, v2);
  }
  long long val(int l, int r) { return val(l, r + 1, 1, 0, s); }
  long long val(int pl) { return val(pl, pl + 1, 1, 0, s); }
  void add(int l, int r, int v, int tl, int tr, long long val) {
    if (r <= tl || tr <= l) return;
    push(v);
    if (l <= tl && tr <= r) return void(adder(v, val));
    int tm = tl + tr >> 1;
    add(l, r, 2 * v, tl, tm, val);
    add(l, r, 2 * v + 1, tm, tr, val);
    upd(v);
  }
  void add(int v, long long val) {
    v += s;
    t[v].first += val;
    v >>= 1;
    while (v) upd(v), v >>= 1;
  }
  void add(int l, int r, long long t) { add(l, r + 1, 1, 0, s, t); }
  void show() {
    for (long long i = 1; i < 2 * s; i++) {
      cout << '\t' << '{' << t[i].first << "   " << t[i].second << "} ";
      if ((i & (i + 1)) == 0) cout << endl;
    }
  }
};
int n, m, q;
vector<int> val;
vector<int> ver_by_val;
vector<vector<int>> e;
vector<pair<int, int>> all;
vector<pair<int, int>> qr;
bool viv = false;
vector<int> p;
vector<vector<int>> kids;
int nxt;
vector<int> spliter;
vector<int> value_st;
Tree st;
set<pair<int, int>> seg;
void read() {
  cin >> n >> m >> q;
  val.resize(n);
  ver_by_val.resize(n);
  for (auto &i : val) cin >> i, i--;
  for (int i = 0; i < n; i++) ver_by_val[val[i]] = i;
  e.resize(n);
  for (int i = 0; i < m; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    e[a].push_back(b);
    e[b].push_back(a);
    all.push_back({a, b});
  }
  qr.resize(q);
  set<int> left;
  for (int i = 0; i < m; i++) left.insert(i);
  for (auto &p : qr) {
    cin >> p.first >> p.second;
    p.first--;
    p.second--;
    if (p.first) left.erase(p.second);
  }
  for (auto ed : left) qr.push_back({1, ed});
  q = qr.size();
}
int pr(int v) {
  if (p[v] == v) return v;
  return p[v] = pr(p[v]);
}
bool unit(int v, int u) {
  v = pr(v);
  u = pr(u);
  if (v == u) return false;
  int s = nxt++;
  kids[s].push_back(v);
  kids[s].push_back(u);
  p[v] = s;
  p[u] = s;
  return true;
}
void prepare() {
  p.resize(2 * n - 1);
  kids.resize(2 * n - 1);
  for (int i = 0; i < p.size(); i++) p[i] = i;
  nxt = n;
  vector<long long> ord;
  for (auto p : qr)
    if (p.first) ord.push_back(p.second);
  reverse(ord.begin(), ord.end());
  for (auto num : ord) {
    int v = all[num].first;
    int u = all[num].second;
    if (unit(v, u))
      spliter.push_back(nxt - 1);
    else
      spliter.push_back(-1);
  }
  if (viv) {
    for (int i = 0; i < nxt; i++) {
      cout << "kids[" << i << "] = ";
      for (auto v : kids[i]) cout << v << ' ';
      cout << endl;
    }
    cout << "Spliter = ";
    for (auto i : spliter) cout << i << ' ';
    cout << endl;
  }
}
vector<int> tin, tout;
int t = 0;
void DFS(int v) {
  int my_val = -mod;
  if (v < n) my_val = val[v];
  value_st[t] = my_val;
  tin[v] = t++;
  for (auto u : kids[v])
    if (tin[u] == -1) DFS(u);
  value_st[t] = my_val;
  tout[v] = t++;
}
void build() {
  tin.resize(nxt, -1);
  tout.resize(nxt, -1);
  value_st.resize(2 * nxt);
  for (int i = nxt - 1; i >= 0; i--) {
    if (tin[i] == -1) {
      DFS(i);
      seg.insert({tin[i], tout[i]});
    }
  }
  st.build(value_st);
  if (viv) {
    for (int i = 0; i < nxt; i++) {
      cout << "seg[" << i << "] = " << tin[i] << ' ' << tout[i] << endl;
    }
  }
}
bool out_seg(int p, pair<int, int> seg) {
  if (p < seg.first || seg.second < p) return true;
  return false;
}
void work() {
  if (viv) st.show();
  for (auto p : qr) {
    if (p.first) {
      int s = spliter.back();
      spliter.pop_back();
      if (s != -1) {
        int v = kids[s][0];
        int u = kids[s][1];
        if (viv) {
          cout << "split vertex " << s << " on " << v << " and " << u << endl;
        }
        seg.erase({tin[s], tout[s]});
        seg.insert({tin[v], tout[v]});
        seg.insert({tin[u], tout[u]});
        if (viv) {
          for (auto p : seg)
            cout << '{' << p.first << ", " << p.second << "}, ";
          cout << endl;
        }
      }
    } else {
      int v = p.second;
      int pl = tin[v];
      if (viv) cout << "find for " << v << " include " << tin[v] << endl;
      auto z = seg.lower_bound({pl, pl});
      while (out_seg(pl, *z)) z--;
      auto pr = *z;
      int l = pr.first;
      int r = pr.second;
      auto ans = st.val(l, r);
      if (ans >= 0) {
        cout << ans + 1 << '\n';
        v = ver_by_val[ans];
        st.add(tin[v], tin[v], -mod);
        st.add(tout[v], tout[v], -mod);
        if (viv) st.show();
      } else {
        cout << "0\n";
      }
    }
  }
}
void solve() {
  read();
  prepare();
  build();
  work();
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  long long t = 1;
  while (t--) solve();
  return 0;
}

```