There are n cities in Cyberland, numbered from 1 to n, connected by m bidirectional roads. The j-th road connects city aj and bj.

For tourists, souvenirs are sold in every city of Cyberland. In particular, city i sell it at a price of wi.

Now there are q queries for you to handle. There are two types of queries:

  * "C a w": The price in city a is changed to w.
  * "A a b": Now a tourist will travel from city a to b. He will choose a route, he also doesn't want to visit a city twice. He will buy souvenirs at the city where the souvenirs are the cheapest (possibly exactly at city a or b). You should output the minimum possible price that he can buy the souvenirs during his travel.



More formally, we can define routes as follow:

  * A route is a sequence of cities [x1, x2, ..., xk], where k is a certain positive integer.
  * For any 1 ≤ i < j ≤ k, xi ≠ xj.
  * For any 1 ≤ i < k, there is a road connecting xi and xi + 1.
  * The minimum price of the route is min(wx1, wx2, ..., wxk).
  * The required answer is the minimum value of the minimum prices of all valid routes from a to b.

Input

The first line of input contains three integers n, m, q (1 ≤ n, m, q ≤ 105), separated by a single space.

Next n lines contain integers wi (1 ≤ wi ≤ 109).

Next m lines contain pairs of space-separated integers aj and bj (1 ≤ aj, bj ≤ n, aj ≠ bj).

It is guaranteed that there is at most one road connecting the same pair of cities. There is always at least one valid route between any two cities.

Next q lines each describe a query. The format is "C a w" or "A a b" (1 ≤ a, b ≤ n, 1 ≤ w ≤ 109).

Output

For each query of type "A", output the corresponding answer.

Examples

Input

3 3 3
1
2
3
1 2
2 3
1 3
A 2 3
C 1 5
A 2 3


Output

1
2


Input

7 9 4
1
2
3
4
5
6
7
1 2
2 5
1 5
2 3
3 4
2 4
5 6
6 7
5 7
A 2 3
A 6 4
A 6 7
A 3 3


Output

2
1
5
3

Note

For the second sample, an optimal routes are:

From 2 to 3 it is [2, 3].

From 6 to 4 it is [6, 5, 1, 2, 4].

From 6 to 7 it is [6, 5, 7].

From 3 to 3 it is [3].

<image>
#include <bits/stdc++.h>
using namespace std;
void rd(int &x) {
  x = 0;
  static char c;
  while (c = getchar(), c < 48)
    ;
  do x = x * 10 + (c ^ 48);
  while (c = getchar(), c > 47);
}
void ptn(int x) {
  static int stk[35];
  int tp = 0;
  for (; x; x /= 10) stk[tp++] = x % 10 ^ 48;
  for (int i = (tp)-1, _s = (0); i >= _s; --i) putchar(stk[i]);
  putchar('\n');
}
inline void Min(int &a, int b) {
  if (b < a) a = b;
}
const int N = (int)1e5 + 5, NODE = N << 1;
int val[N], lst[N], bcc_cnt, bcc_id[N], allc, id[N], refer[NODE];
bool is_cut[N];
pair<int, int> edge[N << 1];
vector<int> bcc[N];
void add_edge(int u, int v) {
  static int tot_edge;
  edge[tot_edge] = pair<int, int>(v, lst[u]);
  lst[u] = tot_edge++;
}
struct Heap {
  priority_queue<int, vector<int>, greater<int>> p, q;
  inline void Push(int x) { p.push(x); }
  inline void Del(int x) {
    for (q.push(x); !q.empty() && p.top() == q.top(); p.pop(), q.pop())
      ;
  }
  inline int Top() { return p.top(); }
} hp[N];
namespace BCC_Tree {
int val[NODE], lst[NODE], par[NODE], dep[NODE], sz[NODE], hev[NODE], tp[NODE],
    dfn[NODE];
pair<int, int> edge[NODE << 1];
namespace Segment_Tree {
const int M = 1 << 18;
int arr[NODE], tr[M << 1];
void cons() {
  for (int i = (0), _t = (M << 1); i < _t; ++i) tr[i] = INT_MAX;
  for (int i = (1), _t = (allc + 1); i < _t; ++i) tr[i + M] = arr[i];
  for (int k = (M)-1, _s = (1); k >= _s; --k)
    tr[k] = min(tr[(k << 1)], tr[(k << 1 | 1)]);
}
void modify(int k, int val) {
  arr[k] = val;
  for (tr[k += M] = val, k >>= 1; k; k >>= 1)
    tr[k] = min(tr[(k << 1)], tr[(k << 1 | 1)]);
}
int query(int L, int R) {
  int res = INT_MAX;
  for (L += M - 1, R += M + 1; L ^ R ^ 1; L >>= 1, R >>= 1) {
    if (~L & 1) Min(res, tr[L ^ 1]);
    if (R & 1) Min(res, tr[R ^ 1]);
  }
  return res;
}
}  // namespace Segment_Tree
inline void init() { memset(lst, -1, allc + 1 << 2); }
void add_edge(int u, int v) {
  static int tot_edge;
  edge[tot_edge] = pair<int, int>(v, lst[u]);
  lst[u] = tot_edge++;
}
void add_edges(int u, int v) {
  add_edge(u, v);
  add_edge(v, u);
}
void dfs(int u) {
  sz[u] = 1;
  for (int i = lst[u]; ~i; i = edge[i].second) {
    int v = edge[i].first;
    if (v == par[u]) continue;
    par[v] = u;
    if (v <= bcc_cnt) hp[v].Del(::val[refer[u]]);
    dep[v] = dep[u] + 1;
    dfs(v);
    sz[u] += sz[v];
    if (sz[v] > sz[hev[u]]) hev[u] = v;
  }
}
void redfs(int u) {
  static int dfs_clock;
  if (u <= bcc_cnt)
    val[u] = hp[u].Top();
  else
    val[u] = ::val[refer[u]];
  Segment_Tree::arr[dfn[u] = ++dfs_clock] = val[u];
  if (hev[u]) {
    tp[hev[u]] = tp[u];
    redfs(hev[u]);
  }
  for (int i = lst[u]; ~i; i = edge[i].second) {
    int v = edge[i].first;
    if (v == par[u] || v == hev[u]) continue;
    redfs(tp[v] = v);
  }
}
void cope() {
  dfs(1);
  redfs(tp[1] = 1);
  Segment_Tree::cons();
}
int query(int u, int v) {
  int res = INT_MAX;
  for (; tp[u] != tp[v]; u = par[tp[u]]) {
    if (dep[tp[u]] < dep[tp[v]]) swap(u, v);
    Min(res, Segment_Tree::query(dfn[tp[u]], dfn[u]));
  }
  if (dep[u] > dep[v]) swap(u, v);
  Min(res, Segment_Tree::query(dfn[u], dfn[v]));
  if (u <= bcc_cnt && par[u]) Min(res, Segment_Tree::arr[dfn[par[u]]]);
  return res;
}
}  // namespace BCC_Tree
void dfs(int u, int par = 0) {
  static int dfs_clock, dfn[N], lowlink[N], tp;
  static pair<int, int> stk[N << 1];
  lowlink[u] = dfn[u] = ++dfs_clock;
  int cnt_ch = 0;
  for (int i = lst[u]; ~i; i = edge[i].second) {
    int v = edge[i].first;
    if (v == par) continue;
    if (!dfn[v]) {
      stk[tp++] = pair<int, int>(u, v);
      ++cnt_ch;
      dfs(v, u);
      Min(lowlink[u], lowlink[v]);
      if (lowlink[v] >= dfn[u]) {
        is_cut[u] = true;
        ++bcc_cnt;
        for (;;) {
          --tp;
          int elm_u = stk[tp].first, elm_v = stk[tp].second;
          if (bcc_id[elm_u] != bcc_cnt)
            bcc[bcc_id[elm_u] = bcc_cnt].push_back(elm_u);
          if (bcc_id[elm_v] != bcc_cnt)
            bcc[bcc_id[elm_v] = bcc_cnt].push_back(elm_v);
          if (elm_u == u && elm_v == v) break;
        }
      }
    } else if (dfn[v] < dfn[u]) {
      stk[tp++] = pair<int, int>(u, v);
      Min(lowlink[u], dfn[v]);
    }
  }
  if (u == 1 && cnt_ch == 1) is_cut[u] = false;
}
void modify(int u, int value) {
  if (is_cut[u]) {
    if (BCC_Tree::par[id[u]]) {
      hp[BCC_Tree::par[id[u]]].Del(val[u]);
    }
    BCC_Tree::Segment_Tree::modify(BCC_Tree::dfn[id[u]], value);
    if (BCC_Tree::par[id[u]]) {
      hp[BCC_Tree::par[id[u]]].Push(value);
      BCC_Tree::Segment_Tree::modify(BCC_Tree::dfn[BCC_Tree::par[id[u]]],
                                     hp[BCC_Tree::par[id[u]]].Top());
    }
  } else {
    hp[id[u]].Del(val[u]);
    hp[id[u]].Push(value);
    BCC_Tree::Segment_Tree::modify(BCC_Tree::dfn[id[u]], hp[id[u]].Top());
  }
  val[u] = value;
}
int query(int u, int v) {
  if (u == v) return val[u];
  return BCC_Tree::query(id[u], id[v]);
}
int main() {
  int n, m, q;
  rd(n), rd(m), rd(q);
  memset(lst, -1, n + 1 << 2);
  for (int i = (1), _t = (n + 1); i < _t; ++i) rd(val[i]);
  for (int u, v; m--;) {
    rd(u), rd(v);
    add_edge(u, v);
    add_edge(v, u);
  }
  dfs(1);
  allc = bcc_cnt;
  for (int i = (1), _t = (n + 1); i < _t; ++i) {
    if (is_cut[i])
      refer[id[i] = ++allc] = i;
    else
      id[i] = bcc_id[i];
  }
  BCC_Tree::init();
  for (int i = (1), _t = (bcc_cnt + 1); i < _t; ++i)
    for (int u : bcc[i]) {
      if (is_cut[u]) BCC_Tree::add_edges(i, id[u]);
      hp[i].Push(val[u]);
    }
  BCC_Tree::cope();
  for (int a, b; q--;) {
    static char str[5];
    scanf("%s", str);
    rd(a), rd(b);
    if (str[0] == 'C')
      modify(a, b);
    else
      ptn(query(a, b));
  }
  return 0;
}
