#include <bits/stdc++.h>
using namespace std;
template <typename T>
void read(T& a) {
  static char c;
  static bool b;
  for (c = getchar(), b = false; !isdigit(c); c = getchar())
    if (c == '-') b = true;
  for (a = 0; isdigit(c); c = getchar()) a = a * 10 + (c - '0');
  if (b) a = -a;
}
template <>
void read<char>(char& c) {
  do {
    c = getchar();
  } while (isspace(c));
}
template <typename T, typename... Args>
void read(T& a, Args&... args) {
  read(a);
  read(args...);
}
const int MAXN = 2e5 + 10;
const int MAXM = MAXN;
const int INF = 0x3f3f3f3f;
template <typename T>
struct Segment {
  struct Node {
    int l, r, lc, rc;
    T v;
  } t[MAXN << 2];
  int cnt;
  void maintain(int x) { t[x].v = min(t[t[x].lc].v, t[t[x].rc].v); }
  int create() { return ++cnt; }
  int build(int l, int r, T* origin) {
    int x = create();
    t[x].l = l, t[x].r = r;
    if (l != r) {
      int mid = l + r;
      mid >>= 1;
      t[x].lc = build(l, mid, origin);
      t[x].rc = build(mid + 1, r, origin);
      maintain(x);
    } else
      t[x].v = origin[l];
    return x;
  }
  T query(int x, int l, int r) {
    if (l <= t[x].l && t[x].r <= r) return t[x].v;
    int mid = t[x].l + t[x].r;
    mid >>= 1;
    if (r <= mid)
      return query(t[x].lc, l, r);
    else if (l > mid)
      return query(t[x].rc, l, r);
    return min(query(t[x].lc, l, r), query(t[x].rc, l, r));
  }
  void modify(int x, int l, int v) {
    if (t[x].l == t[x].r) {
      t[x].v = v;
      return;
    }
    int mid = t[x].l + t[x].r;
    mid >>= 1;
    if (l <= mid)
      modify(t[x].lc, l, v);
    else
      modify(t[x].rc, l, v);
    maintain(x);
  }
};
struct BaseGraph {
  struct Lfs {
    int to, nxt;
  } t[MAXM << 1];
  int head[MAXN], cnt;
  void add(int x, int y) {
    ++cnt;
    t[cnt].to = y;
    t[cnt].nxt = head[x];
    head[x] = cnt;
  }
  void add2(int x, int y) { add(x, y), add(y, x); }
};
struct Graph : BaseGraph {
  int dfn[MAXN], low[MAXN], tm, n;
  stack<int> st;
  BaseGraph* gh;
  void tarjan(int x) {
    dfn[x] = low[x] = ++tm;
    st.push(x);
    for (int i = head[x]; i; i = t[i].nxt) {
      int v = t[i].to;
      if (dfn[v]) {
        low[x] = min(low[x], dfn[v]);
      } else {
        tarjan(v);
        low[x] = min(low[x], low[v]);
        if (low[v] >= dfn[x]) {
          ++n;
          int y;
          gh->add2(x, n);
          do {
            y = st.top();
            st.pop();
            gh->add2(y, n);
          } while (y != v);
        }
      }
    }
  }
  void tarjan(int n, BaseGraph* p) {
    this->n = n;
    this->gh = p;
    tarjan(1);
  }
} G;
struct NewGraph : BaseGraph {
  multiset<int> R[MAXN];
  int sz[MAXN], son[MAXN], top[MAXN];
  int dfn[MAXN], dep[MAXN], fa[MAXN], id;
  int w[MAXN], v[MAXN], rt;
  int bn, n;
  Segment<int> S;
  void prepare(int bn, int n) {
    fa[1] = id = 0;
    dep[1] = 1;
    dfs(1);
    deal(1, 1);
    this->bn = bn;
    this->n = n;
    for (int x = bn + 1; x <= n; ++x) {
      for (int i = head[x]; i; i = t[i].nxt) {
        int v = t[i].to;
        if (v == fa[x]) continue;
        R[x].insert(this->v[v]);
      }
      if (R[x].empty()) {
        v[x] = INF;
      } else
        v[x] = *R[x].begin();
    }
    for (int i = 1; i <= n; ++i) w[dfn[i]] = v[i];
    rt = S.build(1, n, w);
  }
  void dfs(int x) {
    sz[x] = 1;
    son[x] = 0;
    for (int i = head[x]; i; i = t[i].nxt) {
      int v = t[i].to;
      if (v == fa[x]) continue;
      dep[v] = dep[x] + 1;
      fa[v] = x;
      dfs(v);
      sz[x] += sz[v];
      if (sz[son[x]] < sz[v]) son[x] = v;
    }
  }
  void deal(int x, int topf) {
    if (!x) return;
    dfn[x] = ++id;
    top[x] = topf;
    deal(son[x], topf);
    for (int i = head[x]; i; i = t[i].nxt) {
      int v = t[i].to;
      if (v == fa[x]) continue;
      if (v == son[x]) continue;
      deal(v, v);
    }
  }
  void modify(int x, int val) {
    int f = fa[x];
    if (f) {
      R[f].erase(R[f].find(v[x]));
      R[f].insert(val);
      v[f] = *R[f].begin();
      S.modify(rt, dfn[f], v[f]);
    }
    v[x] = val;
    S.modify(rt, dfn[x], val);
  }
  int query(int x, int y) {
    int ans = INF;
    while (top[x] != top[y]) {
      if (dep[top[x]] < dep[top[y]]) swap(x, y);
      ans = min(ans, S.query(rt, dfn[top[x]], dfn[x]));
      x = fa[top[x]];
    }
    if (dep[x] > dep[y]) swap(x, y);
    ans = min(ans, S.query(rt, dfn[x], dfn[y]));
    if (x > bn) ans = min(ans, v[fa[x]]);
    return ans;
  }
} G2;
int main() {
  int n, m, T;
  read(n, m, T);
  for (int i = 1; i <= n; ++i) read(G2.v[i]);
  for (int i = 1; i <= m; ++i) {
    int x, y;
    read(x, y);
    G.add2(x, y);
  }
  G.tarjan(n, &G2);
  G2.prepare(n, G.n);
  while (T--) {
    char c;
    int x, y;
    read(c, x, y);
    switch (c) {
      case 'A':
        printf("%d\n", G2.query(x, y));
        break;
      case 'C':
        G2.modify(x, y);
        break;
    }
  }
  return 0;
}
