#include <bits/stdc++.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using pii = std::pair<int, int>;
const int N = 1e6 + 10;
const int INF = 2e9;
int n, m, q, w[N];
std::multiset<int> set[N];
std::vector<int> g[N], bcc[N];
namespace LCT {
int tot, fa[N], dep[N], siz[N], son[N], top[N], dfn[N], rnk[N];
void dfs1(int u, int f) {
fa[u] = f, dep[u] = dep[f] + 1, siz[u] = 1;
for (auto v : bcc[u]) {
if (v == f) continue;
dfs1(v, u);
siz[u] += siz[v];
if (siz[son[u]] < siz[v]) son[u] = v;
}
}
void dfs2(int u, int ftop) {
dfn[u] = ++tot, rnk[tot] = u, top[u] = ftop;
if (son[u]) dfs2(son[u], ftop);
for (auto v : bcc[u])
if (v ^ fa[u] && v ^ son[u]) dfs2(v, v);
}
void work() {
dfs1(1, 0);
dfs2(1, 0);
}
}
namespace Tarjan {
int stk[N], top;
int cnt, tot, dfn[N], low[N];
void add(int cnt, int u) {
bcc[cnt].push_back(u);
bcc[u].push_back(cnt);
}
void record(int u, int v) {
add(tot, u);
while (stk[top] != v)
add(tot, stk[top--]);
add(tot, stk[top--]);
}
void solve(int u, int fa) {
dfn[u] = low[u] = ++cnt;
stk[++top] = u;
for (auto v : g[u]) {
if (v == fa) continue;
if (!dfn[v]) {
solve(v, u), low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u]) ++tot, record(u, v);
} else low[u] = min(low[u], dfn[v]);
}
}
void work() {
tot = n;
solve(1, 0);
}
}
namespace SegmentTree {
int a[4 * N];
void pushup(int u) {
a[u] = min(a[u * 2], a[u * 2 + 1]);
}
bool outRange(int l, int r, int L, int R) {
return L > r || R < l;
}
bool inRange(int l, int r, int L, int R) {
return l >= L && r <= R;
}
void build(int u, int l, int r) {
if (l == r) {
a[u] = w[LCT::rnk[l]];
return ;
}
int mid = l + r >> 1;
build(u * 2, l, mid);
build(u * 2 + 1, mid + 1, r);
pushup(u);
}
int query(int u, int l, int r, int L, int R) {
if (outRange(l, r, L, R)) return INF;
if (inRange(l, r, L, R)) return a[u];
int mid = l + r >> 1;
return min(query(u * 2, l, mid, L, R),
query(u * 2 + 1, mid + 1, r, L, R));
}
void update(int u, int l, int r, int p, int x) {
if (outRange(l, r, p, p)) return ;
if (inRange(l, r, p, p)) {
a[u] = x;
return ;
}
int mid = l + r >> 1;
update(u * 2, l, mid, p, x);
update(u * 2 + 1, mid + 1, r, p, x);
pushup(u);
}
}
void input() {
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);
for (int i = 1, u, v; i <= m; ++i) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
}
void init() {
Tarjan::work();
LCT::work();
for (int i = 1; i <= n; ++i)
if (LCT::fa[i]) set[LCT::fa[i]].insert(w[i]);
for (int i = n + 1; i <= Tarjan::tot; ++i)
w[i] = *set[i].begin();
SegmentTree::build(1, 1, Tarjan::tot);
}
void work1(int p, int x) {
SegmentTree::update(1, 1, Tarjan::tot, LCT::dfn[p], x);
if (LCT::fa[p]) {
int f = LCT::fa[p];
set[f].erase(set[f].lower_bound(w[p]));
set[f].insert(x);
if (w[f] != *set[f].begin()) {
w[f] = *set[f].begin();
SegmentTree::update(1, 1, Tarjan::tot, LCT::dfn[f], w[f]);
}
}
w[p] = x;
}
void work2(int x, int y) {
int ans = INF;
while (LCT::top[x] != LCT::top[y]) {
if (LCT::dep[LCT::top[x]] < LCT::dep[LCT::top[y]])
std::swap(x, y);
ans = min(ans, SegmentTree::query(1, 1, Tarjan::tot, LCT::dfn[LCT::top[x]], LCT::dfn[x]));
x = LCT::fa[LCT::top[x]];
}
if (LCT::dfn[x] > LCT::dfn[y]) std::swap(x, y);
ans = min(ans, SegmentTree::query(1, 1, Tarjan::tot, LCT::dfn[x], LCT::dfn[y]));
if (x > n) ans = min(ans, w[LCT::fa[x]]);
printf("%d\n", ans);
}
void solve() {
init();
char op;
for (int a, b; q; --q) {
getchar();
scanf("%c%d%d", &op, &a, &b);
if (op == 'C') work1(a, b);
else if (op == 'A') work2(a, b);
else exit(1);
}
}
signed main() {
input();
solve();
return 0;
}