#include<bits/stdc++.h>
using namespace std;
const int N = (int)2e5 + 7;
const int inf = 0x3f3f3f3f;
int n, m, q, w[N], pa[N], depth[N];
vector<int> G[N], G2[N];
multiset<int> mulset[N];
int sz[N], son[N], top[N];
int in[N], ot[N], idx;
int bcc_cnt;
int dfn[N], low[N], dfs_clock;
int stk[N], tot;
char op[10];
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
struct SegmentTree {
int a[N << 2];
void build(int l, int r, int rt) {
a[rt] = inf;
if(l == r) return;
int mid = l + r >> 1;
build(lson); build(rson);
}
void update(int p, int val, int l, int r, int rt) {
if(l == r) {
a[rt] = val;
return;
}
int mid = l + r >> 1;
if(p <= mid) update(p, val, lson);
else update(p, val, rson);
a[rt] = min(a[rt << 1], a[rt << 1 | 1]);
}
int query(int L, int R, int l, int r, int rt) {
if(R < l || r < L || R < L) return inf;
if(L <= l && r <= R) return a[rt];
int mid = l + r >> 1;
return min(query(L, R, lson), query(L, R, rson));
}
} Tree;
void tarjan(int u, int fa) {
dfn[u] = low[u] = ++dfs_clock;
stk[++tot] = u;
for(auto &v : G[u]) {
if(v == fa) continue;
if(!dfn[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u]) {
++bcc_cnt;
while(1) {
int t = stk[tot--];
G2[t].push_back(bcc_cnt);
G2[bcc_cnt].push_back(t);
mulset[bcc_cnt].insert(w[t]);
if(t == v) break;
}
G2[u].push_back(bcc_cnt);
G2[bcc_cnt].push_back(u);
mulset[bcc_cnt].insert(w[u]);
}
}
else if(dfn[v] < dfn[u]) {
low[u] = min(low[u], dfn[v]);
}
}
}
void dfs(int u, int fa) {
pa[u] = fa;
sz[u] = 1;
son[u] = 0;
depth[u] = depth[fa] + 1;
for(auto &v : G[u]) {
if(v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
if(sz[son[u]] < sz[v]) {
son[u] = v;
}
}
}
void dfs2(int u, int fa, int from) {
top[u] = from;
in[u] = ++idx;
if(son[u]) dfs2(son[u], u, from);
for(auto &v : G[u]) {
if(v == fa || v == son[u]) continue;
dfs2(v, u, v);
}
ot[u] = idx;
}
int solve(int u, int v) {
int ans = inf;
while(top[u] != top[v]) {
if(depth[top[u]] < depth[top[v]]) swap(u, v);
ans = min(ans, Tree.query(in[top[u]], in[u], 1, bcc_cnt, 1));
u = pa[top[u]];
}
if(depth[u] < depth[v]) swap(u, v);
ans = min(ans, Tree.query(in[v], in[u], 1, bcc_cnt, 1));
if(v > n) ans = min(ans, w[pa[v]]);
return ans;
}
int main() {
scanf("%d%d%d", &n, &m, &q);
bcc_cnt = n;
for(int i = 1; i <= n; i++) {
scanf("%d", &w[i]);
}
for(int i = 1; i <= m; i++) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
tarjan(1, 0);
for(int i = 1; i <= bcc_cnt; i++) {
G[i] = G2[i];
}
dfs(1, 0);
dfs2(1, 0, 1);
Tree.build(1, bcc_cnt, 1);
for(int i = 1; i <= n; i++) {
Tree.update(in[i], w[i], 1, bcc_cnt, 1);
}
for(int i = n + 1; i <= bcc_cnt; i++) {
mulset[i].insert(inf);
if(pa[i]) mulset[i].erase(mulset[i].lower_bound(w[pa[i]]));
Tree.update(in[i], *mulset[i].begin(), 1, bcc_cnt, 1);
}
while(q--) {
int a, b;
scanf("%s%d%d", op, &a, &b);
if(*op == 'C') {
if(pa[a]) mulset[pa[a]].erase(mulset[pa[a]].lower_bound(w[a]));
w[a] = b;
if(pa[a]) {
mulset[pa[a]].insert(w[a]);
Tree.update(in[pa[a]], *mulset[pa[a]].begin(), 1, bcc_cnt, 1);
}
Tree.update(in[a], w[a], 1, bcc_cnt, 1);
}
else {
printf("%d\n", solve(a, b));
}
}
return 0;
}