#include <cstdio>
#include <vector>
#include <algorithm>
#include <set>

const int MN = 100005;
const int MS = 524288;
const int Inf = 0x7fffffff;

int N, M, Q, cnt;
int w[MN * 2];
std::vector<int> G[MN], T[MN * 2];
std::multiset<int> S[MN * 2];

int dfn[MN * 2], low[MN], dfc;
int stk[MN], tp;

void Tarjan(int u) {
	low[u] = dfn[u] = ++dfc;
	stk[++tp] = u;
	for (auto v : G[u]) {
		if (!dfn[v]) {
			Tarjan(v);
			low[u] = std::min(low[u], low[v]);
			if (low[v] >= dfn[u]) {
				++cnt;
				for (int x = 0; x != v; --tp) {
					x = stk[tp];
					T[cnt].push_back(x);
					T[x].push_back(cnt);
				}
				T[cnt].push_back(u);
				T[u].push_back(cnt);
			}
		}
		else low[u] = std::min(low[u], dfn[v]);
	}
}

int idf[MN * 2], faz[MN * 2], siz[MN * 2], dep[MN * 2], son[MN * 2], top[MN * 2];

void DFS0(int u, int fz) {
	faz[u] = fz, dep[u] = dep[fz] + 1, siz[u] = 1;
	for (auto v : T[u]) if (v != fz) {
		DFS0(v, u);
		siz[u] += siz[v];
		if (siz[son[u]] < siz[v]) son[u] = v;
	}
}

void DFS1(int u, int fz, int tp) {
	dfn[u] = ++dfc, idf[dfc] = u, top[u] = tp;
	if (son[u]) DFS1(son[u], u, tp);
	for (auto v : T[u])
		if (v != fz && v != son[u])
			DFS1(v, u, v);
}

#define li (i << 1)
#define ri (i << 1 | 1)
#define mid ((l + r) >> 1)
#define ls li, l, mid
#define rs ri, mid + 1, r

int dat[MS];

void Build(int i, int l, int r) {
	if (l == r) { dat[i] = w[idf[l]]; return ; }
	Build(ls), Build(rs);
	dat[i] = std::min(dat[li], dat[ri]);
}

void Mdf(int i, int l, int r, int p, int x) {
	if (l == r) { dat[i] = x; return ; }
	if (p <= mid) Mdf(ls, p, x);
	else Mdf(rs, p, x);
	dat[i] = std::min(dat[li], dat[ri]);
}

int Qur(int i, int l, int r, int a, int b)
{
	if (r < a || b < l) return Inf;
	if (a <= l && r <= b) return dat[i];
	return std::min(Qur(ls, a, b), Qur(rs, a, b));
}

int main() {
	scanf("%d%d%d", &N, &M, &Q);
	for (int i = 1; i <= N; ++i)
		scanf("%d", &w[i]);
	cnt = N;
	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), DFS0(1, 0), dfc = 0, DFS1(1, 0, 1);
	for (int i = 1; i <= N; ++i)
    if (faz[i])
		S[faz[i]].insert(w[i]);
	for (int i = N + 1; i <= cnt; ++i)
		w[i] = *S[i].begin();
	Build(1, 1, cnt);
	for (int q = 1; q <= Q; ++q)
    {
		char opt[3]; int x, y;
		scanf("%s%d%d", opt, &x, &y);
		if (*opt == 'C')
        {
			Mdf(1, 1, cnt, dfn[x], y);
			if (faz[x]) {
				int u = faz[x];
				S[u].erase(S[u].lower_bound(w[x]));
				S[u].insert(y);
				if (w[u] != *S[u].begin()) {
					w[u] = *S[u].begin();
					Mdf(1, 1, cnt, dfn[u], w[u]);
				}
			}
			w[x] = y;
		}
		else {
			int Ans = Inf;
			while (top[x] != top[y]) {
				if (dep[top[x]] < dep[top[y]])
					std::swap(x, y);
				Ans = std::min(Ans, Qur(1, 1, cnt, dfn[top[x]], dfn[x]));
				x = faz[top[x]];
			}
			if (dfn[x] > dfn[y]) std::swap(x, y);
			Ans = std::min(Ans, Qur(1, 1, cnt, dfn[x], dfn[y]));
			if (x > N) Ans = std::min(Ans, w[faz[x]]);
			printf("%d\n", Ans);
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5,inf=1e9;
vector<int>v[N],dcc[N];
struct Link{int to,nxt;}l[N<<1];
int n,m,Q,w[N],head[N],tot;
inline int read(){
	int s=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
	while(ch>='0'&&ch<='9') s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
	return s*f;
}
inline void add(int x,int y){
	l[++tot].to=y;l[tot].nxt=head[x];head[x]=tot;
}
int dfn[N],low[N],bl[N],cut[N],st[N],val[N],rt,now,tp,cnt;
void tarjan(int x){
	dfn[x]=low[x]=++now;st[++tp]=x;int flag=0;
	for(auto y:v[x]){
		if(!dfn[y]){
			tarjan(y);
			low[x]=min(low[x],low[y]);
			if(low[y]>=dfn[x]){
				flag++;
				if(x!=rt||flag>1) cut[x]=1;
				cnt++;int z=0;
				do{
					z=st[tp--];bl[z]=cnt;
					dcc[cnt].push_back(z);
					add(z,cnt),add(cnt,z);
				}while(z!=y);
				dcc[cnt].push_back(x);
				add(x,cnt),add(cnt,x);
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
}

multiset<int>s[N];
int son[N],sz[N],top[N],fa[N],rk[N],id[N],d[N],node;
void dfs(int x,int f){
	sz[x]=1;fa[x]=f;d[x]=d[f]+1;
	for(int i=head[x];i;i=l[i].nxt){
		int y=l[i].to;
		if(y==f) continue;
		dfs(y,x);sz[x]+=sz[y];
		if(sz[y]>sz[son[x]]) son[x]=y;
	}
}
void dfs(int x,int f,int tp){
	top[x]=tp;id[x]=++node;rk[node]=x;
	if(!son[x])return;dfs(son[x],x,tp);
	for(int i=head[x];i;i=l[i].nxt){
		int y=l[i].to;
		if(y==f||y==son[x]) continue;
		dfs(y,x,y);
	}
	if(x<=n) return;
	for(int i=head[x];i;i=l[i].nxt)
		if(l[i].to!=f) /*cout<<"push  "<<id[x]<<" "<<w[l[i].to]<<" "<<endl,*/s[id[x]].insert(w[l[i].to]);
}

int mx[N<<2];
#define lc(k) k<<1
#define rc(k) k<<1|1
#define IT multiset<int>::iterator
void build(int k,int l,int r){
	if(l==r) return mx[k]=*(s[l].begin()),void();//cout<<"excuse me ? "<<k<<" "<<l<<" "<<rk[9]<<" "<<s[rk[9]].begin()<<" "<<mx[k]<<endl,void();
	int mid=l+r>>1;
	build(lc(k),l,mid);build(rc(k),mid+1,r);
	mx[k]=min(mx[lc(k)],mx[rc(k)]);
}
void modify(int k,int l,int r,int pos){
	if(l==r) return mx[k]=*(s[l].begin()),void();
	int mid=l+r>>1;
	if(mid>=pos) modify(lc(k),l,mid,pos);
	if(mid<pos)modify(rc(k),mid+1,r,pos);
	mx[k]=min(mx[lc(k)],mx[rc(k)]);
}
int query(int k,int l,int r,int L,int R){
	if(L<=l&&r<=R) return mx[k];
	int mid=l+r>>1,res=inf;
	if(mid>=L) res=min(res,query(lc(k),l,mid,L,R));
	if(mid<R)res=min(res,query(rc(k),mid+1,r,L,R));
	return res;
}
int get_ans(int x,int y){
	int ans=inf,fx=top[x],fy=top[y];
	//cout<<x<<" "<<y<<endl;
	while(fx!=fy){
		if(d[fx]<d[fy]) swap(x,y),swap(fx,fy);
		ans=min(ans,query(1,1,node,id[fx],id[x]));
		x=fa[fx];fx=top[x];
	}
	if(d[x]>d[y]) swap(x,y);
	ans=min(ans,query(1,1,node,id[x],id[y]));
	//cout<<x<<" "<<y<<" "<<id[x]<<" "<<id[y]<<" x="<<query(1,1,node,id[x],id[x])<<" y="<<query(1,1,node,id[y],id[y])<<" "<<ans<<endl;
	if(x>n) ans=min(ans,w[fa[x]]);
	return ans;
}
int main(){
	n=read(),m=read(),Q=read();
	for(int i=1;i<=n;++i) w[i]=read();
	for(int i=1;i<=m;++i){
		int x=read(),y=read();
		v[x].push_back(y);
		v[y].push_back(x);
	}
	cnt=n;
	for(int i=1;i<=n;++i) if(!dfn[i]) rt=i,tarjan(i);

	dfs(1,0);dfs(1,0,1);
	for(int i=1;i<=n;++i) s[id[i]].insert(w[i]);
	//cout<<"---------------"<<rk[9]<<" "<<*(s[9].begin())<<endl;
	build(1,1,node);
	char opt[3];
	for(int i=1;i<=Q;++i){
		scanf("%s",opt);int x=read(),y=read();
		if(opt[0]=='A') printf("%d\n",get_ans(x,y));
		if(opt[0]=='C'){

			s[id[x]].erase(w[x]);s[id[fa[x]]].erase(w[x]);w[x]=y;

			s[id[x]].insert(w[x]);s[id[fa[x]]].insert(w[x]);

			modify(1,1,node,id[x]);
			modify(1,1,node,id[fa[x]]);
		}
	}
	return 0;

}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int INF = 0x3f3f3f3f;
vector<int> G[N],T[N<<1];
int low[N],dfn[N<<1],rk[N<<1],top[N<<1],fa[N<<1],siz[N<<1],son[N<<1],st[N],val[N<<1];
int cnt,tp,num,n,m,q;
bool ins[N];
multiset<int> S[N];
void tarjan(int u){
    low[u]=dfn[u]=++cnt;
    st[++tp]=u; ins[u]=true;
    for(auto v:G[u]){
        if(!dfn[v]){
            tarjan(v); low[u]=min(low[u],low[v]);
            if(low[v]==dfn[u]){
                ++num;
                for(int x=0;x!=v;--tp){
                    x=st[tp]; fa[x]=num;
                    T[num].push_back(x);
                    S[num].insert(val[x]);
                }
                T[u].push_back(num);
                fa[num]=u;
                val[num]=*S[num].begin();
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
}
int tr[N<<3];
void build(int k,int l,int r){
    if(l==r){
        tr[k]=val[rk[l]];
        return ;
    }
    int mid=(l+r)>>1,lk=k<<1,rk=k<<1|1;
    build(lk,l,mid); build(rk,mid+1,r);
    tr[k]=min(tr[lk],tr[rk]);
}
void update(int p,int v,int k,int l,int r){
    if(p>r||p<l) return ;
    if(l==r){
        tr[k]=v; return ;
    }
    int mid=(l+r)>>1,lk=k<<1,rk=k<<1|1;
    update(p,v,lk,l,mid); update(p,v,rk,mid+1,r);
    tr[k]=min(tr[lk],tr[rk]);
}
int query(int a,int b,int k,int l,int r){
    if(a>r||b<l) return INF;
    if(a<=l&&r<=b) return tr[k];
    int mid=(l+r)>>1,lk=k<<1,rk=k<<1|1;
    return min(query(a,b,lk,l,mid),query(a,b,rk,mid+1,r));
}
void dfs1(int u){
    siz[u]=1; son[u]=0;
    for(auto v:T[u]){
        dfs1(v); siz[u]+=siz[v];
        if(!son[u]||siz[son[u]]<siz[v]) son[u]=v;
    }
}
void dfs2(int u,int t){
    rk[dfn[u]=++cnt]=u; top[u]=t;
    if(son[u]) dfs2(son[u],t);
    for(auto v:T[u]){
        if(v==son[u]) continue;
        dfs2(v,v);
    }
}
void mod(int u,int x){
    if(fa[u]>n) S[fa[u]].erase(S[fa[u]].find(val[u]));
    val[u]=x;
    if(fa[u]>n){
        S[fa[u]].insert(val[u]);
        val[fa[u]]=*S[fa[u]].begin();
        update(dfn[fa[u]],val[fa[u]],1,1,num);
    }
    update(dfn[u],val[u],1,1,num);
}
int ask(int u,int v){
    int rs=INF;
    while(top[u]!=top[v]){
        if(dfn[u]>dfn[v]) swap(u,v);
        rs=min(rs,query(dfn[top[v]],dfn[v],1,1,num));
        v=fa[top[v]];
    }
    if(dfn[u]>dfn[v]) swap(u,v);
    rs=min(rs,query(dfn[u],dfn[v],1,1,num));
    if(u>n) rs=min(rs,val[fa[u]]);
    return rs;
}
int main(){
    scanf("%d %d %d",&n,&m,&q);
    for(int i=1;i<=n;++i) scanf("%d",&val[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);
    }
    num=n; tarjan(1);
    dfs1(1); cnt=0; dfs2(1,1);
    build(1,1,num);
    char op[3]; int u,v;
    while(q--){
        scanf("%s %d %d",op,&u,&v);
        if(op[0]=='C') mod(u,v);
        else printf("%d\n",ask(u,v));
    }
}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int INF = 0x3f3f3f3f;
vector<int> G[N],T[N<<1];
int low[N],dfn[N<<1],rk[N<<1],top[N<<1],fa[N<<1],siz[N<<1],son[N<<1],st[N],val[N<<1];
int cnt,tp,num,n,m,q;
bool ins[N];
multiset<int> S[N<<1];
void tarjan(int u){
    low[u]=dfn[u]=++cnt;
    st[++tp]=u; ins[u]=true;
    for(auto v:G[u]){
        if(!dfn[v]){
            tarjan(v); low[u]=min(low[u],low[v]);
            if(low[v]==dfn[u]){
                ++num;
                for(int x=0;x!=v;--tp){
                    x=st[tp]; fa[x]=num;
                    T[num].push_back(x);
                    S[num].insert(val[x]);
                }
                T[u].push_back(num);
                fa[num]=u;
                val[num]=*S[num].begin();
            }
        }
        else low[u]=min(low[u],dfn[v]);
    }
}
int tr[N<<3];
void build(int k,int l,int r){
    if(l==r){
        tr[k]=val[rk[l]];
        return ;
    }
    int mid=(l+r)>>1,lk=k<<1,rk=k<<1|1;
    build(lk,l,mid); build(rk,mid+1,r);
    tr[k]=min(tr[lk],tr[rk]);
}
void update(int p,int v,int k,int l,int r){
    if(p>r||p<l) return ;
    if(l==r){
        tr[k]=v; return ;
    }
    int mid=(l+r)>>1,lk=k<<1,rk=k<<1|1;
    update(p,v,lk,l,mid); update(p,v,rk,mid+1,r);
    tr[k]=min(tr[lk],tr[rk]);
}
int query(int a,int b,int k,int l,int r){
    if(a>r||b<l) return INF;
    if(a<=l&&r<=b) return tr[k];
    int mid=(l+r)>>1,lk=k<<1,rk=k<<1|1;
    return min(query(a,b,lk,l,mid),query(a,b,rk,mid+1,r));
}
void dfs1(int u){
    siz[u]=1; son[u]=0;
    for(auto v:T[u]){
        dfs1(v); siz[u]+=siz[v];
        if(!son[u]||siz[son[u]]<siz[v]) son[u]=v;
    }
}
void dfs2(int u,int t){
    rk[dfn[u]=++cnt]=u; top[u]=t;
    if(son[u]) dfs2(son[u],t);
    for(auto v:T[u]){
        if(v==son[u]) continue;
        dfs2(v,v);
    }
}
void mod(int u,int x){
    if(fa[u]>n) S[fa[u]].erase(S[fa[u]].find(val[u]));
    val[u]=x;
    if(fa[u]>n){
        S[fa[u]].insert(val[u]);
        val[fa[u]]=*S[fa[u]].begin();
        update(dfn[fa[u]],val[fa[u]],1,1,num);
    }
    update(dfn[u],val[u],1,1,num);
}
int ask(int u,int v){
    int rs=INF;
    while(top[u]!=top[v]){
        if(dfn[u]>dfn[v]) swap(u,v);
        rs=min(rs,query(dfn[top[v]],dfn[v],1,1,num));
        v=fa[top[v]];
    }
    if(dfn[u]>dfn[v]) swap(u,v);
    rs=min(rs,query(dfn[u],dfn[v],1,1,num));
    if(u>n) rs=min(rs,val[fa[u]]);
    return rs;
}
int main(){
    scanf("%d %d %d",&n,&m,&q);
    for(int i=1;i<=n;++i) scanf("%d",&val[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);
    }
    num=n; tarjan(1);
    dfs1(1); cnt=0; dfs2(1,1);
    build(1,1,num);
    char op[3]; int u,v;
    while(q--){
        scanf("%s %d %d",op,&u,&v);
        if(op[0]=='C') mod(u,v);
        else printf("%d\n",ask(u,v));
    }
}


#include <stdio.h>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 400005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q;

int w[N], b[N];
struct heap {
	priority_queue<int, vector<int>, greater<int> > Q, E;
	void del(const int& x) { E.push(x); }
	void push(const int& x) { Q.push(x); }
	int gmin() {
		while (!Q.empty() && !E.empty() && Q.top() == E.top()) Q.pop(), E.pop();
		return Q.top();
	}
} g[N];

int totn;
int Tote, Last[N], End[N], Next[N];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N], _Next[N];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}

int s[N], tops;
void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s[++ tops] = x;
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) {
					++ totn;
					ADDE(x, totn);
					do ADDE(s[tops], totn);
					while (s[tops --] != u);
				}
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (fa[x] > n) g[fa[x]].push(w[x]);
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= n; i ++) b[dfn[i]] = w[i];
	for (i = n + 1; i <= totn; i ++) b[dfn[i]] = g[i].gmin();
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			if (fa[x] > n) {
				k = fa[x];
				g[k].del(w[x]);
				g[k].push(y);
				_modify(root, 1, totn, dfn[k], g[k].gmin());
			}
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q;

int w[N], b[N];
struct heap {
	priority_queue<int, vector<int>, greater<int> > Q, E;
	void del(const int& x) { E.push(x); }
	void push(const int& x) { Q.push(x); }
	int gmin() {
		while (!Q.empty() && !E.empty() && Q.top() == E.top()) Q.pop(), E.pop();
		return Q.top();
	}
} g[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N], _Next[N];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}

int s[N], tops;
void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s[++ tops] = x;
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) {
					++ totn;
					ADDE(x, totn);
					do ADDE(s[tops], totn);
					while (s[tops --] != u);
				}
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (fa[x] > n) g[fa[x]].push(w[x]);
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= n; i ++) b[dfn[i]] = w[i];
	for (i = n + 1; i <= totn; i ++) b[dfn[i]] = g[i].gmin();
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			if (fa[x] > n) {
				k = fa[x];
				g[k].del(w[x]);
				g[k].push(y);
				_modify(root, 1, totn, dfn[k], g[k].gmin());
			}
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q;

int w[N], b[N];
struct heap {
	priority_queue<int, vector<int>, greater<int> > Q, E;
	void del(const int& x) { E.push(x); }
	void push(const int& x) { Q.push(x); }
	int gmin() {
		while (!Q.empty() && !E.empty() && Q.top() == E.top()) Q.pop(), E.pop();
		return Q.top();
	}
} g[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N << 1], _Next[N << 1];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}
stack<int> s;

void getbcc(int cp) {
	++ totn;
	ADDE(cp, totn);
	while (!s.empty() && s.top() != cp) {
		int x = s.top(); s.pop();
		ADDE(x, totn);
		g[totn].push(w[x]);
	}
}

void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s.push(x);
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) getbcc(x);
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= n; i ++) b[dfn[i]] = w[i];
	for (i = n + 1; i <= totn; i ++) b[dfn[i]] = g[i].gmin();
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			if (fa[x] > n) {
				k = fa[x];
				g[k].del(w[x]);
				g[k].push(y);
				_modify(root, 1, totn, dfn[k], g[k].gmin());
			}
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q, w[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N << 1], _Next[N << 1];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}
stack<int> s;

void getbcc(int cp) {
	++ totn;
	ADDE(cp, totn);
	w[totn] = INF;
	while (!s.empty() && s.top() != cp) {
		int x = s.top(); s.pop();
		ADDE(x, totn);
		w[totn] = min(w[totn], w[x]);
	}
}

void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s.push(x);
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) getbcc(x);
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

int b[N];
struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= totn; i ++) b[dfn[i]] = w[i];
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			w[x] = y;
			w[fa[x]] = min(w[fa[x]], y);
			_modify(root, 1, totn, dfn[x], y);
			_modify(root, 1, totn, dfn[fa[x]], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q;

int w[N], b[N];
struct heap {
	priority_queue<int, vector<int>, greater<int> > Q, E;
	void del(const int& x) { E.push(x); }
	void push(const int& x) { Q.push(x); }
	int gmin() {
		while (!Q.empty() && !E.empty() && Q.top() == E.top()) Q.pop(), E.pop();
		return Q.top();
	}
} g[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N << 1], _Next[N << 1];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}
stack<int> s;

void getbcc(int cp) {
	++ totn;
	ADDE(cp, totn);
	while (!s.empty() && s.top() != cp) {
		int x = s.top(); s.pop();
		ADDE(x, totn);
	}
}

void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s.push(x);
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) getbcc(x);
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (fa[x] > n) g[fa[x]].push(w[x]);
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= n; i ++) b[dfn[i]] = w[i];
	for (i = n + 1; i <= totn; i ++) b[dfn[i]] = g[i].gmin();
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			if (fa[x] > n) {
				k = fa[x];
				g[k].del(w[x]);
				g[k].push(y);
				_modify(root, 1, totn, dfn[k], g[k].gmin());
			}
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q;

int w[N], b[N];
typedef pair<int, int> pii;
struct heap {
	priority_queue<pii, vector<pii>, greater<pii> > Q, E;
	void del(const pii& x) { E.push(x); }
	void push(const pii& x) { Q.push(x); }
	int gmin() {
		while (!Q.empty() && !E.empty() && Q.top() == E.top()) Q.pop(), E.pop();
		return Q.top().first;
	}
} g[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N << 1], _Next[N << 1];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}
stack<int> s;

void getbcc(int cp) {
	++ totn;
	ADDE(cp, totn);
	while (!s.empty() && s.top() != cp) {
		int x = s.top(); s.pop();
		ADDE(x, totn);
		g[totn].push(pii(w[x], x));
	}
}

void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s.push(x);
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) getbcc(x);
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, g[fa[x]].gmin());
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
//	for (i = 1; i <= Tote; i += 2) printf("%d %d\n", End[i], End[i + 1]);
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= n; i ++) b[dfn[i]] = w[i];
	for (i = n + 1; i <= totn; i ++) b[dfn[i]] = g[i].gmin();
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			if (x != 1) {
				k = fa[x];
				g[k].del(pii(w[x], x));
				g[k].push(pii(y, x));
				_modify(root, 1, totn, dfn[k], g[k].gmin());
			}
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <queue>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q;

int w[N], b[N];
typedef pair<int, int> pii;
struct heap {
	priority_queue<pii, vector<pii>, greater<pii> > Q, E;
	void del(const pii& x) { E.push(x); }
	void push(const pii& x) { Q.push(x); }
	int gmax() {
		while (!Q.empty() && !E.empty() && Q.top() == E.top()) Q.pop(), E.pop();
		return Q.top().first;
	}
} g[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N << 1], _Next[N << 1];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}
stack<int> s;

void getbcc(int cp) {
	++ totn;
	ADDE(cp, totn);
	while (!s.empty() && s.top() != cp) {
		int x = s.top(); s.pop();
		ADDE(x, totn);
		g[totn].push(pii(w[x], x));
	}
}

void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s.push(x);
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) getbcc(x);
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
//	for (i = 1; i <= Tote; i += 2) printf("%d %d\n", End[i], End[i + 1]);
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= n; i ++) b[dfn[i]] = w[i];
	for (i = n + 1; i <= totn; i ++) b[dfn[i]] = g[i].gmax();
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			if (x != 1) {
				k = fa[x];
				g[k].del(pii(w[x], x));
				g[k].push(pii(y, x));
				_modify(root, 1, totn, dfn[k], g[k].gmax());
			}
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
		}
	}
}


#include <stdio.h>
#include <stack>
#include <algorithm>
using namespace std;
const int N = 200005, INF = 1e9 + 7;

char buf[1 << 20], *p1, *p2;
#define GC (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? 0 : *p1 ++)
inline int _R() {
	int d = 0; char t; bool ty = 1;
	while (t = GC, (t < '0' || t > '9') && t != '-');
	t == '-' ? (ty = 0) : (d = t - '0');
	while (t = GC, t >= '0' && t <= '9') d = (d << 3) + (d << 1) + t - '0';
	return ty ? d : -d;
}
inline void _S(char *c) {
	char *t = c, ch;
	while (ch = GC, ch == ' ' || ch == '\r' || ch == '\n') ;
	*t ++ = ch;
	while (ch = GC, ch != ' ' && ch != '\r' && ch != '\n') *t ++ = ch;
	*t = 0;
}

int n, m, q, w[N];

int totn;
int Tote, Last[N], End[N << 1], Next[N << 1];
void ADDE(int x, int y) {
	End[++ Tote] = y, Next[Tote] = Last[x], Last[x] = Tote;
	End[++ Tote] = x, Next[Tote] = Last[y], Last[y] = Tote;
}

int vtt, fa[N], dfn[N], low[N];

int _Tote, _Last[N], _End[N << 1], _Next[N << 1];
void EDDA(int x, int y) {
	_End[++ _Tote] = y, _Next[_Tote] = _Last[x], _Last[x] = _Tote;
	_End[++ _Tote] = x, _Next[_Tote] = _Last[y], _Last[y] = _Tote;
}
stack<int> s;

void getbcc(int cp) {
	++ totn;
	ADDE(cp, totn);
	w[totn] = INF;
	while (!s.empty() && s.top() != cp) {
		int x = s.top(); s.pop();
		ADDE(x, totn);
		w[totn] = min(w[totn], w[x]);
	}
}

void tarjan(int x) {
	dfn[x] = low[x] = ++ vtt;
	s.push(x);
	for (int i = _Last[x], u; i; i = _Next[i])
		if (u = _End[i], u != fa[x])
			if (!dfn[u]) {
				fa[u] = x;
				tarjan(u);
				low[x] = min(low[x], low[u]);
				if (dfn[x] <= low[u]) getbcc(x);
			}
			else low[x] = min(low[x], dfn[u]);
}

int dep[N], top[N], hson[N];
int dfs_init(int x) {
	int maxx = 0, sz = 1, tmp, i, u;
	dep[x] = dep[fa[x]] + 1;
	for (i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x])
			if (fa[u] = x, tmp = dfs_init(u), sz += tmp, tmp > maxx)
				maxx = tmp, hson[x] = u;
	return sz;
}

void dfs_make(int x, int tp) {
	dfn[x] = ++ vtt;
	top[x] = tp;
	if (hson[x]) dfs_make(hson[x], tp);
	for (int i = Last[x], u; i; i = Next[i])
		if (u = End[i], u != fa[x] && u != hson[x])
			dfs_make(u, u);
}

int b[N];
struct Node {
	Node *Son[2];
	int val;
} pool[N << 2], *tl, *root, *null;

void _pushup(Node *p) {
	p -> val = min(p -> Son[0] -> val, p -> Son[1] -> val);
}

void _build(Node *&p, int l, int r) {
	p = ++ tl;
	if (l < r) {
		int mid = l + r >> 1;
		_build(p -> Son[0], l, mid);
		_build(p -> Son[1], mid + 1, r);
		_pushup(p);
	} else p -> val = b[l];
}

void _init() {
	null = tl = pool;
	null -> Son[0] = null -> Son[1] = null;
	_build(root, 1, totn);
}

void _modify(Node* p, int l, int r, int k, int d) {
	if (l == r) { p -> val = d; return; }
	int mid = l + r >> 1;
	if (k <= mid) _modify(p -> Son[0], l, mid, k, d);
	else _modify(p -> Son[1], mid + 1, r, k, d);
	_pushup(p);
}

int _query(Node* p, int l, int r, int x, int y) {
	if (x <= l && r <= y) return p -> val;
	int mid = l + r >> 1, lm = INF, rm = INF;
	if (x <= mid) lm = _query(p -> Son[0], l, mid, x, y);
	if (mid < y) rm = _query(p -> Son[1], mid + 1, r, x, y);
	return min(lm, rm);
}

int gans(int x, int y) {
	int ret = INF;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		ret = min(ret, _query(root, 1, totn, dfn[top[x]], dfn[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	ret = min(ret, _query(root, 1, totn, dfn[x], dfn[y]));
	if (x > n) ret = min(ret, w[fa[x]]);
	return ret;
}

int main() {
	int i, j, k, x, y;
	char opt[3];

	totn = n = _R(), m = _R(), q = _R();
	for (i = 1; i <= n; i ++) w[i] = _R();
	for (i = 1; i <= m; i ++) {
		x = _R(), y = _R();
		EDDA(x, y);
	}

	tarjan(1); vtt = 0;
	dfs_init(1);
	dfs_make(1, 1);
	for (i = 1; i <= totn; i ++) b[dfn[i]] = w[i];
	_init();
	for (i = 1; i <= q; i ++) {
		_S(opt), x = _R(), y = _R();
		if (opt[0] == 'A') printf("%d\n", gans(x, y));
		else {
			w[x] = y;
			_modify(root, 1, totn, dfn[x], y);
			if (x != 1 && y < w[fa[x]]) {
				w[fa[x]] = y;
				_modify(root, 1, totn, dfn[fa[x]], y);
			}
		}
	}
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cassert>
#include<cctype>
#include<set>
#include<vector>
using namespace std;
inline int getint()
{
  char ch;
  while(!isdigit(ch=getchar())) ;
  int x=ch-'0';
  while(isdigit(ch=getchar())) x=x*10+ch-'0';
  return x;
}
inline char getalpha()
{
  char ch;
  while(!isalpha(ch=getchar())) ;
  return ch;
}
const int N=100010,M=100010,Inf=1<<30;
struct node
{
  int l,r,minv;
}t[N<<2]={};
int n,m,q,w[N]={},last[N]={},end[M+M]={},next[M+M]={},total_edge=0;
int c[N]={},add[N]={},totc=0,fa[N]={},is_cut[N]={};
int size[N]={},hson[N]={},top[N]={},d[N]={},pos[N]={},rpos[N]={},ptot=0;
multiset<int> minw[N];
inline void add_edge(int u,int v)
{
  next[++total_edge]=last[u];
  last[u]=total_edge;
  end[total_edge]=v;
}
void init()
{
  n=getint(),m=getint(),q=getint();
  for(int i=1;i<=n;++i)
    w[i]=getint();
  for(int i=1,u=0,v=0;i<=m;++i)
    {
      u=getint(),v=getint();
      add_edge(u,v),add_edge(v,u);
    }
}
void Tarjan(int now,int f)
{
  static int dfn[N]={},low[N]={},tot_dfn=0;
  static int s[N]={},top=0;
  dfn[now]=low[now]=++tot_dfn;
  s[++top]=now;
  for(int i=last[now];i;i=next[i])
    {
      int j=end[i];
      if(j==f)
	continue;
      if(!dfn[j])
	{
	  Tarjan(j,now);
	  if(low[j]>=dfn[now])
	    {
	      is_cut[now]=true;
	      add[++totc]=now;
	      while(s[top+1]!=j)
		c[s[top--]]=totc;
	      c[now]=totc;
	    }
	  else
	    low[now]=min(low[now],low[j]);
	}
      else
	low[now]=min(low[now],dfn[j]);
    }
}
void make_tree(int l,int r,int k)
{
  if(l!=r)
    {
      int mid=(l+r)>>1;
      make_tree(l,mid,k<<1);
      make_tree(mid+1,r,(k<<1)|1);
      t[k].minv=min(t[k<<1].minv,t[(k<<1)|1].minv);
    }
  else
    t[k].minv=*minw[rpos[l]].begin();
  t[k].l=l;
  t[k].r=r;
}
void change(int pos,int k)
{
  if(t[k].l==t[k].r)
    {
      t[k].minv=*minw[rpos[pos]].begin();
      return;
    }
  if(t[k<<1].r>=pos)
    change(pos,k<<1);
  else
    change(pos,(k<<1)|1);
  t[k].minv=min(t[k<<1].minv,t[(k<<1)|1].minv);
}
int minv(int l,int r,int k)
{
  if(t[k].l>=l && t[k].r<=r)
    return t[k].minv;
  int v=Inf;
  if(t[k<<1].r>=l)
    v=min(v,minv(l,r,k<<1));
  if(t[(k<<1)|1].l<=r)
    v=min(v,minv(l,r,(k<<1)|1));
  return v;
}
void Tarjan()
{
  Tarjan(1,0);
  vector<pair<int,int> > e;
  for(int s=1;s<=n;++s)
    for(int i=last[s];i;i=next[i])
      if(c[s]!=c[end[i]])
	e.push_back(make_pair(c[s],c[end[i]]));
  sort(e.begin(),e.end());
  e.erase(unique(e.begin(),e.end()),e.end());
  fill(last+1,last+n+1,0);
  total_edge=0;
  for(int i=e.size()-1;i>=0;--i)
    add_edge(e[i].first,e[i].second);
  for(int i=1;i<=n;++i)
    minw[c[i]].insert(w[i]);
  n=totc;
  make_tree(1,n,1);
}
void dfs1(int s,int f)
{
  size[s]=1;
  fa[s]=f;
  for(int i=last[s];i;i=next[i])
    if(end[i]!=f)
      {
	d[end[i]]=d[s]+1;
	dfs1(end[i],s);
	if(size[end[i]]>size[hson[s]])
	  hson[s]=end[i];
	size[s]+=size[end[i]];
      }
}
void dfs2(int s,int f)
{
  pos[s]=++ptot;
  rpos[ptot]=s;
  if(!top[s])
    top[s]=s;
  if(hson[s])
    {
      top[hson[s]]=top[s];
      dfs2(hson[s],s);
    }
  for(int i=last[s];i;i=next[i])
    if(end[i]!=f && end[i]!=hson[s])
      dfs2(end[i],s);
}
void HLD()
{
  dfs1(c[1],0);
  dfs2(c[1],0);
  make_tree(1,n,1);
}
int calc(int a,int b)
{
  if(a==b)
    return w[a];
  int x=c[a],y=c[b];
  if(d[x]>d[y])
    swap(x,y),swap(a,b);
  if(x==y)
    return min(*minw[x].begin(),w[add[x]]);
  int ans=Inf,tx=top[x],ty=top[y],cx=is_cut[a]*a,cy=is_cut[b]*b;
  while(tx!=ty)
    {
      if(d[tx]<d[ty])
	swap(x,y),swap(tx,ty),swap(cx,cy);
      ans=min(ans,minv(pos[tx],pos[x],1));
      cx=add[tx];
      x=fa[tx];
      tx=top[x];
    }
  if(d[x]>d[y])
    swap(x,y),swap(cx,cy);
  if(d[x]<d[y])
    ans=min(ans,minv(pos[x]+1,pos[y],1)),y=rpos[pos[x]+1],cy=add[y];
  if(cx==cy)
    ans=min(ans,w[cx]);
  else
    ans=min(ans,min(*minw[x].begin(),w[add[x]]));
  return ans;
}
void query()
{
  for(int i=1;i<=q;++i)
    {
      if(getalpha()=='C')
	{
	  int x=getint(),y=getint();
	  minw[c[x]].erase(minw[c[x]].find(w[x]));
	  minw[c[x]].insert(w[x]=y);
	  change(pos[c[x]],1);
	}
      else
	{
	  int a=getint(),b=getint();
	  printf("%d\n",calc(a,b));
	}
    }
}
int main()
{
  init();
  Tarjan();
  HLD();
  query();
  return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cassert>
#include<cctype>
#include<set>
#include<vector>
using namespace std;

namespace PROG {
inline int getint()
{
  char ch;
  while(!isdigit(ch=getchar())) ;
  int x=ch-'0';
  while(isdigit(ch=getchar())) x=x*10+ch-'0';
  return x;
}
inline char getalpha()
{
  char ch;
  while(!isalpha(ch=getchar())) ;
  return ch;
}
const int N=100010,M=100010,Inf=1<<30;
struct node
{
  int l,r,minv;
}t[N<<2]={};
int n,m,q,w[N]={},last[N]={},end[M+M]={},next[M+M]={},total_edge=0;
int c[N]={},add[N]={},totc=0,fa[N]={},is_cut[N]={};
int size[N]={},hson[N]={},top[N]={},d[N]={},pos[N]={},rpos[N]={},ptot=0;
multiset<int> minw[N];
inline void add_edge(int u,int v)
{
  next[++total_edge]=last[u];
  last[u]=total_edge;
  end[total_edge]=v;
}
void init()
{
  n=getint(),m=getint(),q=getint();
  for(int i=1;i<=n;++i)
    w[i]=getint();
  for(int i=1,u=0,v=0;i<=m;++i)
    {
      u=getint(),v=getint();
      add_edge(u,v),add_edge(v,u);
    }
}
void Tarjan(int now,int f)
{
  static int dfn[N]={},low[N]={},tot_dfn=0;
  static int s[N]={},top=0;
  dfn[now]=low[now]=++tot_dfn;
  s[++top]=now;
  for(int i=last[now];i;i=next[i])
    {
      int j=end[i];
      if(j==f)
	continue;
      if(!dfn[j])
	{
	  Tarjan(j,now);
	  if(low[j]>=dfn[now])
	    {
	      is_cut[now]=true;
	      add[++totc]=now;
	      while(s[top+1]!=j)
		c[s[top--]]=totc;
	      c[now]=totc;
	    }
	  else
	    low[now]=min(low[now],low[j]);
	}
      else
	low[now]=min(low[now],dfn[j]);
    }
}
void make_tree(int l,int r,int k)
{
  if(l!=r)
    {
      int mid=(l+r)>>1;
      make_tree(l,mid,k<<1);
      make_tree(mid+1,r,(k<<1)|1);
      t[k].minv=min(t[k<<1].minv,t[(k<<1)|1].minv);
    }
  else
    t[k].minv=*minw[rpos[l]].begin();
  t[k].l=l;
  t[k].r=r;
}
void change(int pos,int k)
{
  if(t[k].l==t[k].r)
    {
      t[k].minv=*minw[rpos[pos]].begin();
      return;
    }
  if(t[k<<1].r>=pos)
    change(pos,k<<1);
  else
    change(pos,(k<<1)|1);
  t[k].minv=min(t[k<<1].minv,t[(k<<1)|1].minv);
}
int minv(int l,int r,int k)
{
  if(t[k].l>=l && t[k].r<=r)
    return t[k].minv;
  int v=Inf;
  if(t[k<<1].r>=l)
    v=min(v,minv(l,r,k<<1));
  if(t[(k<<1)|1].l<=r)
    v=min(v,minv(l,r,(k<<1)|1));
  return v;
}
void Tarjan()
{
  Tarjan(1,0);
  vector<pair<int,int> > e;
  for(int s=1;s<=n;++s)
    for(int i=last[s];i;i=next[i])
      if(c[s]!=c[end[i]])
	e.push_back(make_pair(c[s],c[end[i]]));
  sort(e.begin(),e.end());
  e.erase(unique(e.begin(),e.end()),e.end());
  fill(last+1,last+n+1,0);
  total_edge=0;
  for(int i=e.size()-1;i>=0;--i)
    add_edge(e[i].first,e[i].second);
  for(int i=1;i<=n;++i)
    minw[c[i]].insert(w[i]);
  n=totc;
  make_tree(1,n,1);
}
void dfs1(int s,int f)
{
  size[s]=1;
  fa[s]=f;
  for(int i=last[s];i;i=next[i])
    if(end[i]!=f)
      {
	d[end[i]]=d[s]+1;
	dfs1(end[i],s);
	if(size[end[i]]>size[hson[s]])
	  hson[s]=end[i];
	size[s]+=size[end[i]];
      }
}
void dfs2(int s,int f)
{
  pos[s]=++ptot;
  rpos[ptot]=s;
  if(!top[s])
    top[s]=s;
  if(hson[s])
    {
      top[hson[s]]=top[s];
      dfs2(hson[s],s);
    }
  for(int i=last[s];i;i=next[i])
    if(end[i]!=f && end[i]!=hson[s])
      dfs2(end[i],s);
}
void HLD()
{
  dfs1(c[1],0);
  dfs2(c[1],0);
  make_tree(1,n,1);
}
int calc(int a,int b)
{
  if(a==b)
    return w[a];
  int x=c[a],y=c[b];
  if(d[x]>d[y])
    swap(x,y),swap(a,b);
  if(x==y)
    return min(*minw[x].begin(),w[add[x]]);
  int ans=Inf,tx=top[x],ty=top[y],cx=is_cut[a]*a,cy=is_cut[b]*b;
  while(tx!=ty)
    {
      if(d[tx]<d[ty])
	swap(x,y),swap(tx,ty),swap(cx,cy);
      ans=min(ans,minv(pos[tx],pos[x],1));
      cx=add[tx];
      x=fa[tx];
      tx=top[x];
    }
  if(d[x]>d[y])
    swap(x,y),swap(cx,cy);
  if(d[x]<d[y])
    ans=min(ans,minv(pos[x]+1,pos[y],1)),y=rpos[pos[x]+1],cy=add[y];
  if(cx==cy)
    ans=min(ans,w[cx]);
  else
    ans=min(ans,min(*minw[x].begin(),w[add[x]]));
  return ans;
}
void query()
{
  for(int i=1;i<=q;++i)
    {
      if(getalpha()=='C')
	{
	  int x=getint(),y=getint();
	  minw[c[x]].erase(minw[c[x]].find(w[x]));
	  minw[c[x]].insert(w[x]=y);
	  change(pos[c[x]],1);
	}
      else
	{
	  int a=getint(),b=getint();
	  printf("%d\n",calc(a,b));
	}
    }
}
int main()
{
  init();
  Tarjan();
  HLD();
  query();
  return 0;
}
}

int main(void) {
  PROG::main();
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cassert>
#include<cctype>
#include<set>
#include<vector>
using namespace std;
inline int getint()
{
  char ch;
  while(!isdigit(ch=getchar())) ;
  int x=ch-'0';
  while(isdigit(ch=getchar())) x=x*10+ch-'0';
  return x;
}
inline char getalpha()
{
  char ch;
  while(!isalpha(ch=getchar())) ;
  return ch;
}
const int N=100010,M=100010,Inf=1<<30;
struct node
{
  int l,r,minv;
}t[N<<2]={};
int n,m,q,w[N]={},last[N]={},end[M+M]={},next[M+M]={},total_edge=0;
int c[N]={},add[N]={},totc=0,fa[N]={},is_cut[N]={};
int size[N]={},hson[N]={},top[N]={},d[N]={},pos[N]={},rpos[N]={},ptot=0;
multiset<int> minw[N];
inline void add_edge(int u,int v)
{
  next[++total_edge]=last[u];
  last[u]=total_edge;
  end[total_edge]=v;
}
void init()
{
  n=getint(),m=getint(),q=getint();
  for(int i=1;i<=n;++i)
    w[i]=getint();
  for(int i=1,u=0,v=0;i<=m;++i)
    {
      u=getint(),v=getint();
      add_edge(u,v),add_edge(v,u);
    }
}
void Tarjan(int now,int f)
{
  static int dfn[N]={},low[N]={},tot_dfn=0;
  static int s[N]={},top=0;
  dfn[now]=low[now]=++tot_dfn;
  s[++top]=now;
  for(int i=last[now];i;i=next[i])
    {
      int j=end[i];
      if(j==f)
	continue;
      if(!dfn[j])
	{
	  Tarjan(j,now);
	  if(low[j]>=dfn[now])
	    {
	      is_cut[now]=true;
	      add[++totc]=now;
	      while(s[top+1]!=j)
		c[s[top--]]=totc;
	      c[now]=totc;
	    }
	  else
	    low[now]=min(low[now],low[j]);
	}
      else
	low[now]=min(low[now],dfn[j]);
    }
}
void Add_Link(int u,int v) {
  Access(u);
  Move_To_Root(v);
  Access(v);
  u->rs = v;
}
void make_tree(int l,int r,int k)
{
  if(l!=r)
    {
      int mid=(l+r)>>1;
      make_tree(l,mid,k<<1);
      make_tree(mid+1,r,(k<<1)|1);
      t[k].minv=min(t[k<<1].minv,t[(k<<1)|1].minv);
    }
  else
    t[k].minv=*minw[rpos[l]].begin();
  t[k].l=l;
  t[k].r=r;
}
void change(int pos,int k)
{
  if(t[k].l==t[k].r)
    {
      t[k].minv=*minw[rpos[pos]].begin();
      return;
    }
  if(t[k<<1].r>=pos)
    change(pos,k<<1);
  else
    change(pos,(k<<1)|1);
  t[k].minv=min(t[k<<1].minv,t[(k<<1)|1].minv);
}
int minv(int l,int r,int k)
{
  if(t[k].l>=l && t[k].r<=r)
    return t[k].minv;
  int v=Inf;
  if(t[k<<1].r>=l)
    v=min(v,minv(l,r,k<<1));
  if(t[(k<<1)|1].l<=r)
    v=min(v,minv(l,r,(k<<1)|1));
  return v;
}
void Tarjan()
{
  Tarjan(1,0);
  vector<pair<int,int> > e;
  for(int s=1;s<=n;++s)
    for(int i=last[s];i;i=next[i])
      if(c[s]!=c[end[i]])
	e.push_back(make_pair(c[s],c[end[i]]));
  sort(e.begin(),e.end());
  e.erase(unique(e.begin(),e.end()),e.end());
  fill(last+1,last+n+1,0);
  total_edge=0;
  for(int i=e.size()-1;i>=0;--i)
    add_edge(e[i].first,e[i].second);
  for(int i=1;i<=n;++i)
    minw[c[i]].insert(w[i]);
  n=totc;
  make_tree(1,n,1);
}
void dfs1(int s,int f)
{
  size[s]=1;
  fa[s]=f;
  for(int i=last[s];i;i=next[i])
    if(end[i]!=f)
      {
	d[end[i]]=d[s]+1;
	dfs1(end[i],s);
	if(size[end[i]]>size[hson[s]])
	  hson[s]=end[i];
	size[s]+=size[end[i]];
      }
}
void dfs2(int s,int f)
{
  pos[s]=++ptot;
  rpos[ptot]=s;
  if(!top[s])
    top[s]=s;
  if(hson[s])
    {
      top[hson[s]]=top[s];
      dfs2(hson[s],s);
    }
  for(int i=last[s];i;i=next[i])
    if(end[i]!=f && end[i]!=hson[s])
      dfs2(end[i],s);
}
void HLD()
{
  dfs1(c[1],0);
  dfs2(c[1],0);
  make_tree(1,n,1);
}
int calc(int a,int b)
{
  if(a==b)
    return w[a];
  int x=c[a],y=c[b];
  if(d[x]>d[y])
    swap(x,y),swap(a,b);
  if(x==y)
    return min(*minw[x].begin(),w[add[x]]);
  int ans=Inf,tx=top[x],ty=top[y],cx=is_cut[a]*a,cy=is_cut[b]*b;
  while(tx!=ty)
    {
      if(d[tx]<d[ty])
	swap(x,y),swap(tx,ty),swap(cx,cy);
      ans=min(ans,minv(pos[tx],pos[x],1));
      cx=add[tx];
      x=fa[tx];
      tx=top[x];
    }
  if(d[x]>d[y])
    swap(x,y),swap(cx,cy);
  if(d[x]<d[y])
    ans=min(ans,minv(pos[x]+1,pos[y],1)),y=rpos[pos[x]+1],cy=add[y];
  if(cx==cy)
    ans=min(ans,w[cx]);
  else
    ans=min(ans,min(*minw[x].begin(),w[add[x]]));
  return ans;
}
void query()
{
  for(int i=1;i<=q;++i)
    {
      if(getalpha()=='C')
	{
	  int x=getint(),y=getint();
	  minw[c[x]].erase(minw[c[x]].find(w[x]));
	  minw[c[x]].insert(w[x]=y);
	  change(pos[c[x]],1);
	}
      else
	{
	  int a=getint(),b=getint();
	  printf("%d\n",calc(a,b));
	}
    }
}
int main()
{
  init();
  Tarjan();
  HLD();
  query();
  return 0;
}


#include<queue>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
vector<int> vec[100010];
struct node{
	int y,next;
}a[400010];int len=1,last[200010];
void ins(int x,int y)
{
	a[++len].y=y;
	a[len].next=last[x];last[x]=len;
}
int w[200010],n,m,Q,A[200010];
int dfn[100010],low[100010],sta[100010],top=0,id=0,cnt;
void tarjan(int x,int fa)
{
	low[x]=dfn[x]=++id;
	sta[++top]=x;
	for(int i=last[x];i;i=a[i].next)
	{
		if(i==(fa^1)) continue;
		int y=a[i].y;
		if(dfn[y]==-1)
		{
			tarjan(y,i);
			if(low[y]>=dfn[x])
			{
				cnt++;
				while(1)
				{
					int t=sta[top--];
					vec[cnt].push_back(t);
					if(t==y) break;
				}
				vec[cnt].push_back(x);
			}
			else low[x]=min(low[x],low[y]);
		}
		else low[x]=min(low[x],dfn[y]);
	}
}
struct trnode{
	int tot,top,fa,dep,son,lc,rc,c;
}tr[400010];int tot=0;
int ys[200010],z=0;
void pre_node(int x,int fa)
{
	tr[x].tot=1;tr[x].fa=fa;tr[x].dep=tr[fa].dep+1;
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y==fa) continue;
		pre_node(y,x);tr[x].tot+=tr[y].tot;
		if(tr[tr[x].son].tot<tr[y].tot) tr[x].son=y;
	}
}
void pre_edge(int x,int top)
{
	ys[x]=++z;tr[x].top=top;
	if(tr[x].son) pre_edge(tr[x].son,top);
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y!=tr[x].fa&&y!=tr[x].son) pre_edge(y,y);
	}
}
struct Priority_queue{
	priority_queue<int,vector<int>,greater<int> > q1,q2;
	Priority_queue()
	{
		while(!q1.empty()) q1.pop();
		while(!q2.empty()) q2.pop();
	}
	void push(int x) {q1.push(x);}
	void del(int x) {q2.push(x);}
	int top()
	{
		while(!q1.empty()&&!q2.empty()&&q1.top()==q2.top()) q1.pop(),q2.pop();
		return q1.top();
	}
}q[200010];
int bt(int l,int r)
{
	int x=++tot;
	if(l!=r)
	{
		int mid=(l+r)/2;
		tr[x].lc=bt(l,mid);
		tr[x].rc=bt(mid+1,r);
		tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
	}
	else tr[x].c=A[l];
	return x;
}
void change(int x,int l,int r,int k,int c)
{
	if(l==r) {tr[x].c=c;return;}
	int mid=(l+r)/2;
	if(k<=mid) change(tr[x].lc,l,mid,k,c);
	else change(tr[x].rc,mid+1,r,k,c);
	tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
}
int findans(int x,int l,int r,int fl,int fr)
{
	if(l==fl&&r==fr) return tr[x].c;
	int mid=(l+r)/2;
	if(fr<=mid) return findans(tr[x].lc,l,mid,fl,fr);
	if(fl>mid) return findans(tr[x].rc,mid+1,r,fl,fr);
	return min(findans(tr[x].lc,l,mid,fl,mid),findans(tr[x].rc,mid+1,r,mid+1,fr));
}
int solve(int x,int y)
{
	int tx=tr[x].top,ty=tr[y].top,ans=1e9+7;
	while(tx!=ty)
	{
		if(tr[tx].dep<tr[ty].dep) swap(tx,ty),swap(x,y);
		ans=min(ans,findans(1,1,n+cnt,ys[tx],ys[x]));
		x=tr[tx].fa;tx=tr[x].top;
	}
	if(tr[x].dep<tr[y].dep) swap(x,y);
	ans=min(ans,findans(1,1,n+cnt,ys[y],ys[x]));
	if(y>n) ans=min(ans,w[tr[y].fa]);
	return ans;
}
int main()
{
	scanf("%d %d %d",&n,&m,&Q);
	for(int i=1;i<=n;i++) scanf("%d",&w[i]);
	for(int i=1;i<=m;i++)
	{
		int x,y;scanf("%d %d",&x,&y);
		ins(x,y);ins(y,x);
	}
	memset(dfn,-1,sizeof(dfn));
	tarjan(1,0);
	len=0;memset(last,0,sizeof(last));
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			ins(x,y);ins(y,x);
		}
	}
	pre_node(1,0);pre_edge(1,1);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			if(y==tr[x].fa) continue;
			q[x].push(w[y]);
		}
		w[x]=q[x].top();
	}
	for(int i=1;i<=n+cnt;i++) A[ys[i]]=w[i];
	bt(1,n+cnt);
	while(Q--)
	{
		char ch[2];scanf("%s",ch);
        int x,y;scanf("%d %d",&x,&y);
        if (ch[0]=='C')
        {
            if(tr[x].fa) q[tr[x].fa].del(w[x]);
            w[x]=y;change(1,1,n+cnt,ys[x],w[x]);
            if(tr[x].fa) q[tr[x].fa].push(w[x]),w[tr[x].fa]=q[tr[x].fa].top(),change(1,1,n+cnt,ys[tr[x].fa],w[tr[x].fa]);
        }
        else printf("%d\n",solve(x,y));
	}
}


#include<queue>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
vector<int> vec[100010];
struct node{
	int y,next;
}a[400010];int len=1,last[200010];
void ins(int x,int y)
{
	a[++len].y=y;
	a[len].next=last[x];last[x]=len;
}
int w[200010],n,m,Q,A[200010];
int dfn[100010],low[100010],sta[100010],top=0,id=0,cnt;
void tarjan(int x,int fa)
{
	low[x]=dfn[x]=++id;
	sta[++top]=x;
	for(int i=last[x];i;i=a[i].next)
	{
		if(i==(fa^1)) continue;
		int y=a[i].y;
		//printf("tarjan:%d %d %d %d\n",x,y,dfn[y],fa);
		if(dfn[y]==-1)
		{
			tarjan(y,i);
			//printf("x y dfn:%d %d %d %d\n",x,y,dfn[x],dfn[y]);
			if(low[y]>=dfn[x])
			{
				cnt++;
				while(1)
				{
					int t=sta[top--];
					vec[cnt].push_back(t);
					if(t==y) break;
				}
				vec[cnt].push_back(x);
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
}
struct trnode{
	int tot,top,fa,dep,son,lc,rc,c;
}tr[400010];int tot=0;
int ys[200010],z=0;
void pre_node(int x,int fa)
{
	tr[x].tot=1;tr[x].fa=fa;tr[x].dep=tr[fa].dep+1;
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y==fa) continue;
		pre_node(y,x);tr[x].tot+=tr[y].tot;
		if(tr[tr[x].son].tot<tr[y].tot) tr[x].son=y;
	}
}
void pre_edge(int x,int top)
{
	//printf("pre_egde %d %d\n",x,top);
	ys[x]=++z;tr[x].top=top;
	if(tr[x].son) pre_edge(tr[x].son,top);
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y!=tr[x].fa&&y!=tr[x].son) pre_edge(y,y);
	}
}
struct Priority_queue{
	priority_queue<int,vector<int>,greater<int> > q1,q2;
	Priority_queue()
	{
		while(!q1.empty()) q1.pop();
		while(!q2.empty()) q2.pop();
	}
	void push(int x) {q1.push(x);}
	void del(int x) {q2.push(x);}
	int top()
	{
		while(!q1.empty()&&!q2.empty()&&q1.top()==q2.top()) q1.pop(),q2.pop();
		return q1.top();
	}
}q[200010];
int bt(int l,int r)
{
	int x=++tot;
	if(l!=r)
	{
		int mid=(l+r)/2;
		tr[x].lc=bt(l,mid);
		tr[x].rc=bt(mid+1,r);
		tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
	}
	else tr[x].c=A[l];
	return x;
}
void change(int x,int l,int r,int k,int c)
{
	if(l==r) {tr[x].c=c;return;}
	int mid=(l+r)/2;
	if(k<=mid) change(tr[x].lc,l,mid,k,c);
	else change(tr[x].rc,mid+1,r,k,c);
	tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
}
int findans(int x,int l,int r,int fl,int fr)
{
	//printf("%d %d %d %d %d\n",x,l,r,fl,fr);
	if(l==fl&&r==fr) return tr[x].c;
	int mid=(l+r)/2;
	if(fr<=mid) return findans(tr[x].lc,l,mid,fl,fr);
	if(fl>mid) return findans(tr[x].rc,mid+1,r,fl,fr);
	return min(findans(tr[x].lc,l,mid,fl,mid),findans(tr[x].rc,mid+1,r,mid+1,fr));
}
int solve(int x,int y)
{
	//printf("ok %d %d\n",x,y);
	int tx=tr[x].top,ty=tr[y].top,ans=1e9+7;
	while(tx!=ty)
	{
		//printf("%d %d %d %d\n",x,y,tx,ty);
		if(tr[tx].dep<tr[ty].dep) swap(tx,ty),swap(x,y);
		ans=min(ans,findans(1,1,n+cnt,ys[tx],ys[x]));
		x=tr[tx].fa;tx=tr[x].top;
	}
	//printf("finish:%d %d %d %d\n",x,y,tx,ty);
	if(tr[x].dep<tr[y].dep) swap(x,y);
	//printf("ys:%d %d\n",ys[x],ys[y]);
	ans=min(ans,findans(1,1,n+cnt,ys[y],ys[x]));
	if(y>n) ans=min(ans,w[tr[y].fa]);
	return ans;
}
int main()
{
	scanf("%d %d %d",&n,&m,&Q);
	for(int i=1;i<=n;i++) scanf("%d",&w[i]);
	for(int i=1;i<=m;i++)
	{
		int x,y;scanf("%d %d",&x,&y);
		ins(x,y);ins(y,x);
	}
	memset(dfn,-1,sizeof(dfn));
	tarjan(1,0);
	len=0;memset(last,0,sizeof(last));
	//printf("cnt:%d\n",cnt);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		//printf("cnt_now:%d:\n",i);
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			//printf("%d ",y);
			ins(x,y);ins(y,x);
		}
		//printf("\n");
	}
	pre_node(1,0);pre_edge(1,1);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			if(y==tr[x].fa) continue;
			q[x].push(w[y]);
		}
		w[x]=q[x].top();
	}
	for(int i=1;i<=n+cnt;i++) A[ys[i]]=w[i];
	bt(1,n+cnt);//printf("ok\n");
	//printf("ys:");for(int i=1;i<=n+cnt;i++) printf("%d ",ys[i]);printf("\n");
	while(Q--)
	{
		char ch[2];scanf("%s",ch);
        int x,y;scanf("%d %d",&x,&y);//printf("x y:%d %d\n",x,y);
        if (ch[0]=='C')
        {
            if(tr[x].fa) q[tr[x].fa].del(w[x]);
            w[x]=y;change(1,1,n+cnt,ys[x],w[x]);
            if(tr[x].fa) q[tr[x].fa].push(w[x]),w[tr[x].fa]=q[tr[x].fa].top(),change(1,1,n+cnt,ys[tr[x].fa],w[tr[x].fa]);
        }
        else printf("%d\n",solve(x,y));
	}
}


#include<queue>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
vector<int> vec[100010];
struct node{
	int y,next;
}a[400010];int len=1,last[200010];
void ins(int x,int y)
{
	a[++len].y=y;
	a[len].next=last[x];last[x]=len;
}
int w[200010],n,m,Q,A[200010];
int dfn[100010],low[100010],sta[100010],top=0,id=0,cnt;
void tarjan(int x,int fa)
{
	low[x]=dfn[x]=++id;
	sta[++top]=x;
	for(int i=last[x];i;i=a[i].next)
	{
		if(i==(fa^1)) continue;
		int y=a[i].y;
		//printf("tarjan:%d %d %d %d\n",x,y,dfn[y],fa);
		if(dfn[y]==-1)
		{
			tarjan(y,i);
			//printf("x y dfn:%d %d %d %d\n",x,y,dfn[x],dfn[y]);
			if(low[y]>=dfn[x])
			{
				cnt++;
				while(1)
				{
					int t=sta[top--];
					vec[cnt].push_back(t);
					if(t==y) break;
				}
				vec[cnt].push_back(x);
			}
		}
		else low[x]=min(low[x],dfn[y]);
	}
}
struct trnode{
	int tot,top,fa,dep,son,lc,rc,c;
}tr[400010];int tot=0;
int ys[200010],z=0;
void pre_node(int x,int fa)
{
	tr[x].tot=1;tr[x].fa=fa;tr[x].dep=tr[fa].dep+1;
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y==fa) continue;
		pre_node(y,x);tr[x].tot+=tr[y].tot;
		if(tr[tr[x].son].tot<tr[y].tot) tr[x].son=y;
	}
}
void pre_edge(int x,int top)
{
	//printf("pre_egde %d %d\n",x,top);
	ys[x]=++z;tr[x].top=top;
	if(tr[x].son) pre_edge(tr[x].son,top);
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y!=tr[x].fa&&y!=tr[x].son) pre_edge(y,y);
	}
}
struct Priority_queue{
	priority_queue<int,vector<int>,greater<int> > q1,q2;
	Priority_queue()
	{
		while(!q1.empty()) q1.pop();
		while(!q2.empty()) q2.pop();
	}
	void push(int x) {q1.push(x);}
	void del(int x) {q2.push(x);}
	int top()
	{
		while(!q1.empty()&&!q2.empty()&&q1.top()==q2.top()) q1.pop(),q2.pop();
		return q1.top();
	}
}q[200010];
int bt(int l,int r)
{
	int x=++tot;
	if(l!=r)
	{
		int mid=(l+r)/2;
		tr[x].lc=bt(l,mid);
		tr[x].rc=bt(mid+1,r);
		tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
	}
	else tr[x].c=A[l];
	return x;
}
void change(int x,int l,int r,int k,int c)
{
	if(l==r) {tr[x].c=c;return;}
	int mid=(l+r)/2;
	if(k<=mid) change(tr[x].lc,l,mid,k,c);
	else change(tr[x].rc,mid+1,r,k,c);
	tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
}
int findans(int x,int l,int r,int fl,int fr)
{
	//printf("%d %d %d %d %d\n",x,l,r,fl,fr);
	if(l==fl&&r==fr) return tr[x].c;
	int mid=(l+r)/2;
	if(fr<=mid) return findans(tr[x].lc,l,mid,fl,fr);
	if(fl>mid) return findans(tr[x].rc,mid+1,r,fl,fr);
	return min(findans(tr[x].lc,l,mid,fl,mid),findans(tr[x].rc,mid+1,r,mid+1,fr));
}
int solve(int x,int y)
{
	//printf("ok %d %d\n",x,y);
	int tx=tr[x].top,ty=tr[y].top,ans=1e9+7;
	while(tx!=ty)
	{
		//printf("%d %d %d %d\n",x,y,tx,ty);
		if(tr[tx].dep<tr[ty].dep) swap(tx,ty),swap(x,y);
		ans=min(ans,findans(1,1,n+cnt,ys[tx],ys[x]));
		x=tr[tx].fa;tx=tr[x].top;
	}
	//printf("finish:%d %d %d %d\n",x,y,tx,ty);
	if(tr[x].dep<tr[y].dep) swap(x,y);
	//printf("ys:%d %d\n",ys[x],ys[y]);
	ans=min(ans,findans(1,1,n+cnt,ys[y],ys[x]));
	if(y!=1) ans=min(ans,w[tr[y].fa]);
	return ans;
}
int main()
{
	scanf("%d %d %d",&n,&m,&Q);
	for(int i=1;i<=n;i++) scanf("%d",&w[i]);
	for(int i=1;i<=m;i++)
	{
		int x,y;scanf("%d %d",&x,&y);
		ins(x,y);ins(y,x);
	}
	memset(dfn,-1,sizeof(dfn));
	tarjan(1,0);
	len=0;memset(last,0,sizeof(last));
	//printf("cnt:%d\n",cnt);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		//printf("cnt:%d:\n",i);
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			//printf("%d ",y);
			ins(x,y);ins(y,x);
		}
		//printf("\n");
	}
	pre_node(1,0);pre_edge(1,1);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			if(y==tr[x].fa) continue;
			q[x].push(w[y]);
		}
		w[x]=q[x].top();
	}
	for(int i=1;i<=n+cnt;i++) A[ys[i]]=w[i];
	bt(1,n+cnt);//printf("ok\n");
	//printf("ys:");for(int i=1;i<=n+cnt;i++) printf("%d ",ys[i]);printf("\n");
	while(Q--)
	{
		char ch[2];scanf("%s",ch);
        int x,y;scanf("%d %d",&x,&y);//printf("x y:%d %d\n",x,y);
        if (ch[0]=='C')
        {
            if(tr[x].fa) q[tr[x].fa].del(w[x]);
            w[x]=y;change(1,1,n+cnt,ys[x],w[x]);
            if(tr[x].fa) q[tr[x].fa].push(w[x]),w[tr[x].fa]=q[tr[x].fa].top(),change(1,1,n+cnt,ys[tr[x].fa],w[tr[x].fa]);
        }
        else printf("%d\n",solve(x,y));
	}
}


#include<queue>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
using namespace std;
vector<int> vec[100010];
struct node{
	int y,next;
}a[400010];int len=1,last[200010];
void ins(int x,int y)
{
	a[++len].y=y;
	a[len].next=last[x];last[x]=len;
}
int w[200010],n,m,Q,A[200010];
int dfn[100010],low[100010],sta[100010],top=0,id=0,cnt;
void tarjan(int x,int fa)
{
	//printf("tarjan:%d\n",x);
	low[x]=dfn[x]=++id;
	sta[++top]=x;
	for(int i=last[x];i;i=a[i].next)
	{
		if(i==(fa^1)) continue;
		int y=a[i].y;
		//printf("tarjan:%d %d %d %d\n",x,y,dfn[y],fa);
		if(dfn[y]==-1)
		{
			tarjan(y,i);
			//printf("x y dfn:%d %d %d %d\n",x,y,dfn[x],dfn[y]);
			if(low[y]>=dfn[x])
			{
				cnt++;
				//printf("cnt:%d:\n",cnt);
				while(1)
				{
					int t=sta[top--];
					//printf("%d ",t);
					vec[cnt].push_back(t);
					if(t==y) break;
				}
				//printf("%d\n",x);
				vec[cnt].push_back(x);
			}
			else low[x]=min(low[x],low[y]);
		}
		else low[x]=min(low[x],dfn[y]);
	}
}
struct trnode{
	int tot,top,fa,dep,son,lc,rc,c;
}tr[400010];int tot=0;
int ys[200010],z=0;
void pre_node(int x,int fa)
{
	tr[x].tot=1;tr[x].fa=fa;tr[x].dep=tr[fa].dep+1;
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y==fa) continue;
		pre_node(y,x);tr[x].tot+=tr[y].tot;
		if(tr[tr[x].son].tot<tr[y].tot) tr[x].son=y;
	}
}
void pre_edge(int x,int top)
{
	//printf("pre_egde %d %d\n",x,top);
	ys[x]=++z;tr[x].top=top;
	if(tr[x].son) pre_edge(tr[x].son,top);
	for(int i=last[x];i;i=a[i].next)
	{
		int y=a[i].y;
		if(y!=tr[x].fa&&y!=tr[x].son) pre_edge(y,y);
	}
}
struct Priority_queue{
	priority_queue<int,vector<int>,greater<int> > q1,q2;
	Priority_queue()
	{
		while(!q1.empty()) q1.pop();
		while(!q2.empty()) q2.pop();
	}
	void push(int x) {q1.push(x);}
	void del(int x) {q2.push(x);}
	int top()
	{
		while(!q1.empty()&&!q2.empty()&&q1.top()==q2.top()) q1.pop(),q2.pop();
		return q1.top();
	}
}q[200010];
int bt(int l,int r)
{
	int x=++tot;
	if(l!=r)
	{
		int mid=(l+r)/2;
		tr[x].lc=bt(l,mid);
		tr[x].rc=bt(mid+1,r);
		tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
	}
	else tr[x].c=A[l];
	return x;
}
void change(int x,int l,int r,int k,int c)
{
	if(l==r) {tr[x].c=c;return;}
	int mid=(l+r)/2;
	if(k<=mid) change(tr[x].lc,l,mid,k,c);
	else change(tr[x].rc,mid+1,r,k,c);
	tr[x].c=min(tr[tr[x].lc].c,tr[tr[x].rc].c);
}
int findans(int x,int l,int r,int fl,int fr)
{
	//printf("%d %d %d %d %d\n",x,l,r,fl,fr);
	if(l==fl&&r==fr) return tr[x].c;
	int mid=(l+r)/2;
	if(fr<=mid) return findans(tr[x].lc,l,mid,fl,fr);
	if(fl>mid) return findans(tr[x].rc,mid+1,r,fl,fr);
	return min(findans(tr[x].lc,l,mid,fl,mid),findans(tr[x].rc,mid+1,r,mid+1,fr));
}
int solve(int x,int y)
{
	//printf("ok %d %d\n",x,y);
	int tx=tr[x].top,ty=tr[y].top,ans=1e9+7;
	while(tx!=ty)
	{
		//printf("%d %d %d %d\n",x,y,tx,ty);
		if(tr[tx].dep<tr[ty].dep) swap(tx,ty),swap(x,y);
		ans=min(ans,findans(1,1,n+cnt,ys[tx],ys[x]));
		x=tr[tx].fa;tx=tr[x].top;
	}
	//printf("finish:%d %d %d %d\n",x,y,tx,ty);
	if(tr[x].dep<tr[y].dep) swap(x,y);
	//printf("ys:%d %d\n",ys[x],ys[y]);
	ans=min(ans,findans(1,1,n+cnt,ys[y],ys[x]));
	if(y>n) ans=min(ans,w[tr[y].fa]);
	return ans;
}
int main()
{
	scanf("%d %d %d",&n,&m,&Q);
	for(int i=1;i<=n;i++) scanf("%d",&w[i]);
	for(int i=1;i<=m;i++)
	{
		int x,y;scanf("%d %d",&x,&y);
		ins(x,y);ins(y,x);
	}
	memset(dfn,-1,sizeof(dfn));
	tarjan(1,0);
	len=0;memset(last,0,sizeof(last));
	//printf("cnt:%d\n",cnt);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		//printf("cnt_now:%d:\n",i);
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			//printf("%d ",y);
			ins(x,y);ins(y,x);
		}
		//printf("\n");
	}
	pre_node(1,0);pre_edge(1,1);
	for(int i=1;i<=cnt;i++)
	{
		int x=i+n;
		for(int j=0;j<vec[i].size();j++)
		{
			int y=vec[i][j];
			if(y==tr[x].fa) continue;
			q[x].push(w[y]);
		}
		w[x]=q[x].top();
	}
	for(int i=1;i<=n+cnt;i++) A[ys[i]]=w[i];
	bt(1,n+cnt);//printf("ok\n");
	//printf("ys:");for(int i=1;i<=n+cnt;i++) printf("%d ",ys[i]);printf("\n");
	while(Q--)
	{
		char ch[2];scanf("%s",ch);
        int x,y;scanf("%d %d",&x,&y);//printf("x y:%d %d\n",x,y);
        if (ch[0]=='C')
        {
            if(tr[x].fa) q[tr[x].fa].del(w[x]);
            w[x]=y;change(1,1,n+cnt,ys[x],w[x]);
            if(tr[x].fa) q[tr[x].fa].push(w[x]),w[tr[x].fa]=q[tr[x].fa].top(),change(1,1,n+cnt,ys[tr[x].fa],w[tr[x].fa]);
        }
        else printf("%d\n",solve(x,y));
	}
}


#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
vector<int> v[N],vv[N];multiset<int> st[N];
struct HPDNode {int fa,top,dep,hson,sz,id;} hpd[N];
int mp[N];
void dfs1(int pos,int fa)
{
    hpd[pos].fa = fa;hpd[pos].dep = hpd[fa].dep + 1;hpd[pos].sz = 1;
    for (auto &i : v[pos])
        if (i != fa)
        {
            dfs1(i,pos);hpd[pos].sz += hpd[i].sz;
            if (hpd[hpd[pos].hson].sz < hpd[i].sz) hpd[pos].hson = i;
        }
}
void dfs2(int pos,int top)
{
    static int idx = 0;
    hpd[pos].id = ++idx;hpd[pos].top = top;mp[idx] = pos;
    if (hpd[pos].hson) dfs2(hpd[pos].hson,top);
    for (auto &i : v[pos])
        if (i != hpd[pos].fa && i != hpd[pos].hson) dfs2(i,i);
}
int val[N];
struct TNode {int l,r,v;} t[N << 2];
inline int lc(int pos) {return pos << 1;}
inline int rc(int pos) {return pos << 1 | 1;}
void build(int pos,int l,int r)
{
	t[pos].l = l;t[pos].r = r;if (l == r) {t[pos].v = val[mp[l]];return;}
	int mid = (l + r) >> 1;build(lc(pos),l,mid);build(rc(pos),mid + 1,r);
	t[pos].v = min(t[lc(pos)].v,t[rc(pos)].v);
}
void modify(int pos,int p,int v)
{
	if (t[pos].l == t[pos].r) {t[pos].v = v;return;}
	int mid = (t[pos].l + t[pos].r) >> 1;
	if (p <= mid) modify(lc(pos),p,v);else modify(rc(pos),p,v);
	t[pos].v = min(t[lc(pos)].v,t[rc(pos)].v);
}
int query(int pos,int l,int r)
{
	if (t[pos].l == l && t[pos].r == r) return t[pos].v;
	int mid = (t[pos].l + t[pos].r) >> 1;
	if (r <= mid) return query(lc(pos),l,r);
	else if (l > mid) return query(rc(pos),l,r);
	else return min(query(lc(pos),l,mid),query(rc(pos),mid + 1,r));
}
int n,m,q,dfn[N],low[N],idx,stk[N],top,cc;
void tarjan(int pos)
{
    dfn[pos] = low[pos] = ++idx;stk[++top] = pos;
    for (auto &i : vv[pos])
        if (!dfn[i])
        {
            tarjan(i);low[pos] = min(low[pos],low[i]);
            if (dfn[pos] == low[i])
            {
                ++cc;
                while (1)
                {
                    int p = stk[top--];v[p].push_back(cc);v[cc].push_back(p);
                    if (p == i) break;
                }
                v[cc].push_back(pos);v[pos].push_back(cc);
            }
        }
        else low[pos] = min(low[pos],dfn[i]);
}
int query_ans(int a,int b)
{
    int ret = INT_MAX;
    while (hpd[a].top != hpd[b].top)
    {
        if (hpd[hpd[a].top].dep < hpd[hpd[b].top].dep) swap(a,b);
        ret = min(ret,query(1,hpd[hpd[a].top].id,hpd[a].id));
        a = hpd[hpd[a].top].fa;
    }
    if (hpd[a].dep > hpd[b].dep) swap(a,b);
    ret = min(ret,query(1,hpd[a].id,hpd[b].id));
    if (a > n) ret = min(ret,val[hpd[a].fa]);
    return ret;
}
int main ()
{
	ios::sync_with_stdio(false);
	cin >> n >> m >> q;cc = n;
    for (int i = 1;i <= n;i++) cin >> val[i];
    int t1,t2;
    for (int i = 1;i <= m;i++)
    {
        cin >> t1 >> t2;vv[t1].push_back(t2);vv[t2].push_back(t1);
    }
    tarjan(1);dfs1(1,0);dfs2(1,1);
    for (int i = 1;i <= n;i++)
        if (hpd[i].fa) st[hpd[i].fa].insert(val[i]);
    for (int i = n + 1;i <= cc;i++) val[i] = *st[i].begin();
    build(1,1,cc);
    while (q--)
    {
        char op[3];cin >> op;
        if (op[0] == 'C')
        {
            cin >> t1 >> t2;modify(1,hpd[t1].id,t2);
            if (hpd[t1].fa)
            {
                auto &rf = st[hpd[t1].fa];
                rf.erase(rf.lower_bound(val[t1]));rf.insert(t2);
                modify(1,hpd[hpd[t1].fa].id,val[hpd[t1].fa] = *rf.begin());
            }
            val[t1] = t2;
        }
        else
        {
            cin >> t1 >> t2;cout << query_ans(t1,t2) << endl;
        }
    }
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const int N2 = N << 1;
const int D = 20;
const int INF = 0x3f3f3f3f;
int a[N2];
multiset<int> mst[N];
int n, nn, m, q;

inline void Min(int &a, int b) { if (a > b) a = b; }

vector<int> edge[N2];
int sz[N2], dep[N2], belong[N2], dfn[N2], num[N2], loc;
int anc[N2][D];
void DFS2(int u, int fa, int chain) {
    dfn[u] = ++loc; num[loc] = u; belong[u] = chain;
    int k = 0;
    for (int v: edge[u]) if (v != fa) if (sz[v] > sz[k]) k = v;
    if (!k) return ;
    DFS2(k, u, chain);
    for (int v: edge[u]) if (!(v == fa || v == k)) DFS2(v, u, v);
}
void DFS(int u, int fa) {
    sz[u] = 1; dep[u] = dep[fa] + 1;
    anc[u][0] = fa;
    for (int i=1; i<D; ++i) anc[u][i] = anc[anc[u][i-1]][i-1];
    for (int v: edge[u]) if (v != fa) {
        DFS(v, u); sz[u] += sz[v];
    }
}
int LCA(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    for (int i=0; i<D; ++i) if ((dep[u]-dep[v]) >> i & 1) u = anc[u][i];
    if (u == v) return u;
    for (int i=D-1; i>=0; --i) if (anc[u][i] != anc[v][i]) {
        u = anc[u][i]; v = anc[v][i];
    }
    return anc[u][0];
}

#define lc o << 1
#define rc o << 1 | 1
#define mid (l + r >> 1)
int mn[N2<<2];
void build(int o, int l, int r) {
    if (l == r) { mn[o] = a[num[l]]; return ; }
    build(lc, l, mid); build(rc, mid+1, r);
    mn[o] = min(mn[o<<1], mn[o<<1|1]);
}
int pos, val, ql, qr;
void modify(int o, int l, int r) {
    if (l == r) { mn[o] = val; return ; }
    if (pos <= mid) modify(lc, l, mid);
    else modify(rc, mid+1, r);
    mn[o] = min(mn[o<<1], mn[o<<1|1]);
}
int query(int o, int l, int r) {
    if (ql > r || qr < l) return INF;
    if (ql <= l && r <= qr) return mn[o];
    return min(query(lc, l, mid), query(rc, mid+1, r));
}

int getMin(int u, int lca) {
    int ret = INF;
    while (belong[u] != belong[lca]) {
        if (dep[belong[u]] < dep[belong[lca]]) swap(u, lca);
        ql = dfn[belong[u]]; qr = dfn[u];
        ret = min(ret, query(1, 1, nn));
        u = anc[belong[u]][0];
    }
    if (dep[belong[u]] < dep[belong[lca]]) swap(u, lca);
    ql = dfn[lca]; qr = dfn[u];
    Min(ret, query(1, 1, nn));
    if (u > n) Min(ret, a[anc[u][0]]);  // 特判
    return ret;
}

void change(int x, int v) {
    int t = anc[x][0] - n;
    if (t > 0) {
        mst[t].erase(mst[t].find(a[x]));
        mst[t].insert(v);
        a[t+n] = *(mst[t].begin());
        pos = dfn[t+n]; val = a[t+n];
        modify(1, 1, nn);
    }
    pos = dfn[x]; a[x] = val = v;
    modify(1, 1, nn);
}

//边双连通分量，时间复杂度O(V+E)
struct Edge {
    int u, v, nex;
}edges[N2];
bool vis[N2];
int head[N], etot;
int bcc_no[N];
int sta[N], top;
int dfs_clock, bcc_cnt;
void addEdge(int u, int v) {
    edges[++etot] = Edge{u, v, head[u]};
    head[u] = etot;
}
int Tarjan(int u, int fa) {
    int lowu = dfn[u] = ++dfs_clock;
    int child = 0, v;
    for (int i=head[u]; i; i=edges[i].nex) if (!dfn[v=edges[i].v]) {
        sta[top++] = i;
        child++;
        int lowv = Tarjan(v, u);
        lowu = min(lowu, lowv);  // 用后代的low函数更新
        if (lowv >= dfn[u]) {
            ++bcc_cnt;
            for (; ;) {
                Edge &e = edges[sta[--top]];
                if (bcc_no[e.u] != bcc_cnt) {
                    edge[bcc_cnt].push_back(e.u);
                    edge[e.u].push_back(bcc_cnt);
                    bcc_no[e.u] = bcc_cnt;
                }
                if (bcc_no[e.v] != bcc_cnt) {
                    edge[bcc_cnt].push_back(e.v);
                    edge[e.v].push_back(bcc_cnt);
                    bcc_no[e.v] = bcc_cnt;
                }
                if (e.u == u && e.v == v) break;
            }
        }
    } else if (dfn[v] < dfn[u] && v != fa) {
        sta[top++] = i;
        lowu = min(lowu, dfn[v]);  // 用反向边更新u的low函数
    }
//    if (fa < 0 && child == 1) iscut[u] = false;
    return lowu;
}
void findBCC() {
    bcc_cnt = n;
    for (int i=1; i<=n; ++i) if (!dfn[i]) Tarjan(i, -1);
}

void prepare() {
    findBCC();
    nn = bcc_cnt;
    sz[0] = dep[0] = 0;
    DFS(1, 0);
    loc = 0;
    DFS2(1, 0, 1);
    for (int i=1; i<=n; ++i) if (anc[i][0] > n) mst[anc[i][0]-n].insert(a[i]);
    for (int i=n+1; i<=nn; ++i) a[i] = *(mst[i-n].begin());
    build(1, 1, nn);
}

int main() {
    scanf("%d%d%d", &n, &m, &q);
    for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
    int u, v;
    for (int i=1; i<=m; ++i) {
        scanf("%d%d", &u, &v);
        addEdge(u, v);
        addEdge(v, u);
    }
    prepare();
    char op[5];
    for (int i=1; i<=q; ++i) {
        scanf("%s%d%d", op, &u, &v);
        if (op[0] == 'C') change(u, v);
        else {
            int lca = LCA(u, v);
            printf("%d\n", min(getMin(u, lca), getMin(v, lca)));
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const int N2 = N << 1;
const int D = 20;
const int INF = 0x3f3f3f3f;
int a[N2];
multiset<int> mst[N];
int n, nn, m, q;

inline void Min(int &a, int b) { if (a > b) a = b; }

vector<int> edge[N2];
int sz[N2], dep[N2], belong[N2], dfn[N2], num[N2], dfs_clock;
int anc[N2][D];
void DFS2(int u, int fa, int chain) {
    dfn[u] = ++dfs_clock; num[dfs_clock] = u; belong[u] = chain;
    int k = 0;
    for (int &v: edge[u]) if (v != fa) if (sz[v] > sz[k]) k = v;
    if (!k) return ;
    DFS2(k, u, chain);
    for (int v: edge[u]) if (!(v == fa || v == k)) DFS2(v, u, v);
}
void DFS(int u, int fa) {
    sz[u] = 1; dep[u] = dep[fa] + 1;
    anc[u][0] = fa;
    for (int i=1; i<D; ++i) anc[u][i] = anc[anc[u][i-1]][i-1];
    for (int &v: edge[u]) if (v != fa) {
        DFS(v, u); sz[u] += sz[v];
    }
}
int LCA(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    for (int i=0; i<D; ++i) if ((dep[u]-dep[v]) >> i & 1) u = anc[u][i];
    if (u == v) return u;
    for (int i=D-1; i>=0; --i) if (anc[u][i] != anc[v][i]) {
        u = anc[u][i]; v = anc[v][i];
    }
    return anc[u][0];
}

#define lc o << 1
#define rc o << 1 | 1
#define mid (l + r >> 1)
int mn[N2<<2];
void build(int o, int l, int r) {
    if (l == r) { mn[o] = a[num[l]]; return ; }
    build(lc, l, mid); build(rc, mid+1, r);
    mn[o] = min(mn[o<<1], mn[o<<1|1]);
}
int pos, val, ql, qr;
void modify(int o, int l, int r) {
    if (l == r) { mn[o] = val; return ; }
    if (pos <= mid) modify(lc, l, mid);
    else modify(rc, mid+1, r);
    mn[o] = min(mn[o<<1], mn[o<<1|1]);
}
int query(int o, int l, int r) {
    if (ql > r || qr < l) return INF;
    if (ql <= l && r <= qr) return mn[o];
    return min(query(lc, l, mid), query(rc, mid+1, r));
}

int getMin(int u, int lca) {
    int ret = INF;
    while (belong[u] != belong[lca]) {
//        if (dep[belong[u]] < dep[belong[lca]]) swap(u, lca);
        ql = dfn[belong[u]]; qr = dfn[u];
        ret = min(ret, query(1, 1, nn));
        u = anc[belong[u]][0];
    }
//    if (dep[belong[u]] < dep[belong[lca]]) swap(u, lca);
    ql = dfn[lca]; qr = dfn[u];
    Min(ret, query(1, 1, nn));
    if (u > n) Min(ret, a[anc[u][0]]);  // 特判
    return ret;
}

void change(int x, int v) {
    int t = anc[x][0] - n;
    if (t > 0) {
        mst[t].erase(mst[t].find(a[x]));
        mst[t].insert(v);
        a[t+n] = *(mst[t].begin());
        pos = dfn[t+n]; val = a[t+n];
        modify(1, 1, nn);
    }
    pos = dfn[x]; a[x] = val = v;
    modify(1, 1, nn);
}

//边双连通分量，时间复杂度O(V+E)
struct Edge {
    int u, v, nex;
}edges[N2];
bool vis[N2];
int head[N], etot;
int bcc_no[N];
int sta[N], top;
int bcc_cnt;
void addEdge(int u, int v) {
    edges[++etot] = Edge{u, v, head[u]};
    head[u] = etot;
}
int Tarjan(int u, int fa) {
    int lowu = dfn[u] = ++dfs_clock;
    int child = 0, v;
    for (int i=head[u]; i; i=edges[i].nex) if (!dfn[v=edges[i].v]) {
        sta[top++] = i;
        child++;
        int lowv = Tarjan(v, u);
        lowu = min(lowu, lowv);  // 用后代的low函数更新
        if (lowv >= dfn[u]) {
            ++bcc_cnt;
            for (; ;) {
                Edge &e = edges[sta[--top]];
                if (bcc_no[e.u] != bcc_cnt) {
                    edge[bcc_cnt].push_back(e.u);
                    edge[e.u].push_back(bcc_cnt);
                    bcc_no[e.u] = bcc_cnt;
                }
                if (bcc_no[e.v] != bcc_cnt) {
                    edge[bcc_cnt].push_back(e.v);
                    edge[e.v].push_back(bcc_cnt);
                    bcc_no[e.v] = bcc_cnt;
                }
                if (e.u == u && e.v == v) break;
            }
        }
    } else if (dfn[v] < dfn[u] && v != fa) {
        sta[top++] = i;
        lowu = min(lowu, dfn[v]);  // 用反向边更新u的low函数
    }
//    if (fa < 0 && child == 1) iscut[u] = false;
    return lowu;
}
void findBCC() {
    bcc_cnt = n;
    for (int i=1; i<=n; ++i) if (!dfn[i]) Tarjan(i, -1);
}

void prepare() {
    findBCC();
    nn = bcc_cnt;
    sz[0] = dep[0] = 0;
    DFS(1, 0);
    dfs_clock = 0;
    DFS2(1, 0, 1);
    for (int i=1; i<=n; ++i) if (anc[i][0] > n) mst[anc[i][0]-n].insert(a[i]);
    for (int i=n+1; i<=nn; ++i) a[i] = *(mst[i-n].begin());
    build(1, 1, nn);
}

int main() {
    scanf("%d%d%d", &n, &m, &q);
    for (int i=1; i<=n; ++i) scanf("%d", &a[i]);
    int u, v;
    for (int i=1; i<=m; ++i) {
        scanf("%d%d", &u, &v);
        addEdge(u, v); addEdge(v, u);
    }
    prepare();
    char op[5];
    for (int i=1; i<=q; ++i) {
        scanf("%s%d%d", op, &u, &v);
        if (op[0] == 'C') change(u, v);
        else {
            int lca = LCA(u, v);
            printf("%d\n", min(getMin(u, lca), getMin(v, lca)));
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;
const int N2 = N << 1;
const int D = 20;
const int INF = 0x3f3f3f3f;
int a[N2];
multiset<int> mst[N];
int n, nn, m, q;

//快速读入(int,long long,double)
inline void read(int &x) {
    x = 0; static char c;
    for (; !(c>='0' && c<='9'); c=getchar());
    for (; c>='0' && c<='9'; x = x*10+(c-'0'), c=getchar());
}

inline void Min(int &a, int b) { if (a > b) a = b; }

vector<int> edge[N2];
int sz[N2], dep[N2], belong[N2], dfn[N2], num[N2], dfs_clock;
int anc[N2][D];
void DFS2(int u, int fa, int chain) {
    dfn[u] = ++dfs_clock; num[dfs_clock] = u; belong[u] = chain;
    int k = 0;
    for (int &v: edge[u]) if (v != fa) if (sz[v] > sz[k]) k = v;
    if (!k) return ;
    DFS2(k, u, chain);
    for (int v: edge[u]) if (!(v == fa || v == k)) DFS2(v, u, v);
}
void DFS(int u, int fa) {
    sz[u] = 1; dep[u] = dep[fa] + 1;
    anc[u][0] = fa;
    for (int i=1; i<D; ++i) anc[u][i] = anc[anc[u][i-1]][i-1];
    for (int &v: edge[u]) if (v != fa) {
        DFS(v, u); sz[u] += sz[v];
    }
}
int LCA(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    for (int i=0; i<D; ++i) if ((dep[u]-dep[v]) >> i & 1) u = anc[u][i];
    if (u == v) return u;
    for (int i=D-1; i>=0; --i) if (anc[u][i] != anc[v][i]) {
        u = anc[u][i]; v = anc[v][i];
    }
    return anc[u][0];
}

#define lc o << 1
#define rc o << 1 | 1
#define mid (l + r >> 1)
int mn[N2<<2];
void build(int o, int l, int r) {
    if (l == r) { mn[o] = a[num[l]]; return ; }
    build(lc, l, mid); build(rc, mid+1, r);
    mn[o] = min(mn[o<<1], mn[o<<1|1]);
}
int pos, val, ql, qr;
void modify(int o, int l, int r) {
    if (l == r) { mn[o] = val; return ; }
    if (pos <= mid) modify(lc, l, mid);
    else modify(rc, mid+1, r);
    mn[o] = min(mn[o<<1], mn[o<<1|1]);
}
int query(int o, int l, int r) {
    if (ql > r || qr < l) return INF;
    if (ql <= l && r <= qr) return mn[o];
    return min(query(lc, l, mid), query(rc, mid+1, r));
}

int getMin(int u, int lca) {
    int ret = INF;
    while (belong[u] != belong[lca]) {
        ql = dfn[belong[u]]; qr = dfn[u];
        ret = min(ret, query(1, 1, nn));
        u = anc[belong[u]][0];
    }
    ql = dfn[lca]; qr = dfn[u];
    Min(ret, query(1, 1, nn));
    if (u > n) Min(ret, a[anc[u][0]]);  // 特判
    return ret;
}

void change(int x, int v) {
    int t = anc[x][0] - n;
    if (t > 0) {
        mst[t].erase(mst[t].find(a[x]));
        mst[t].insert(v);
        a[t+n] = *(mst[t].begin());
        pos = dfn[t+n]; val = a[t+n];
        modify(1, 1, nn);
    }
    pos = dfn[x]; a[x] = val = v;
    modify(1, 1, nn);
}

//边双连通分量，时间复杂度O(V+E)
struct Edge {
    int u, v, nex;
}edges[N2];
bool vis[N2];
int head[N], etot;
int bcc_no[N];
int sta[N], top;
int bcc_cnt;
void addEdge(int u, int v) {
    edges[++etot] = Edge{u, v, head[u]};
    head[u] = etot;
}
int Tarjan(int u, int fa) {
    int lowu = dfn[u] = ++dfs_clock;
    int child = 0, v;
    for (int i=head[u]; i; i=edges[i].nex) if (!dfn[v=edges[i].v]) {
        sta[top++] = i;
        child++;
        int lowv = Tarjan(v, u);
        lowu = min(lowu, lowv);  // 用后代的low函数更新
        if (lowv >= dfn[u]) {
            ++bcc_cnt;
            for (; ;) {
                Edge &e = edges[sta[--top]];
                if (bcc_no[e.u] != bcc_cnt) {
                    edge[bcc_cnt].push_back(e.u);
                    edge[e.u].push_back(bcc_cnt);
                    bcc_no[e.u] = bcc_cnt;
                }
                if (bcc_no[e.v] != bcc_cnt) {
                    edge[bcc_cnt].push_back(e.v);
                    edge[e.v].push_back(bcc_cnt);
                    bcc_no[e.v] = bcc_cnt;
                }
                if (e.u == u && e.v == v) break;
            }
        }
    } else if (dfn[v] < dfn[u] && v != fa) {
        sta[top++] = i;
        lowu = min(lowu, dfn[v]);  // 用反向边更新u的low函数
    }
//    if (fa < 0 && child == 1) iscut[u] = false;
    return lowu;
}
void findBCC() {
    bcc_cnt = n;
    for (int i=1; i<=n; ++i) if (!dfn[i]) Tarjan(i, -1);
}

void prepare() {
    findBCC();
    nn = bcc_cnt;
    sz[0] = dep[0] = 0;
    DFS(1, 0);
    dfs_clock = 0;
    DFS2(1, 0, 1);
    for (int i=1; i<=n; ++i) if (anc[i][0] > n) mst[anc[i][0]-n].insert(a[i]);
    for (int i=n+1; i<=nn; ++i) a[i] = *(mst[i-n].begin());
    build(1, 1, nn);
}

int main() {
//    scanf("%d%d%d", &n, &m, &q);
    read(n); read(m); read(q);
    for (int i=1; i<=n; ++i) read(a[i]); // scanf("%d", &a[i]);
    int u, v;
    for (int i=1; i<=m; ++i) {
//        scanf("%d%d", &u, &v);
        read(u); read(v);
        addEdge(u, v); addEdge(v, u);
    }
    prepare();
    char op[5];
    for (int i=1; i<=q; ++i) {
//        scanf("%s%d%d", op, &u, &v);
        scanf("%s", op); read(u); read(v);
        if (op[0] == 'C') change(u, v);
        else {
            int lca = LCA(u, v);
            printf("%d\n", min(getMin(u, lca), getMin(v, lca)));
        }
    }
    return 0;
}