#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#include <cstdio>//sprintf islower isupper
#include <cstdlib>//malloc  exit strcat itoa system("cls")
#include <iostream>//pair
#include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin);
#include <bitset>
//#include <map>
//#include<unordered_map>
#include <vector>
#include <stack>
#include <set>
#include <string.h>//strstr substr strcat
#include <string>
#include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
#include <cmath>
#include <deque>
#include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
#include <vector>//emplace_back
//#include <math.h>
#include <cassert>
#include <iomanip>
//#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
#include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
//******************
clock_t __START,__END;
double __TOTALTIME;
void _MS(){__START=clock();}
void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;}
//***********************
#define rint register int
#define fo(a,b,c) for(rint a=b;a<=c;++a)
#define fr(a,b,c) for(rint a=b;a>=c;--a)
#define mem(a,b) memset(a,b,sizeof(a))
#define pr printf
#define sc scanf
#define ls rt<<1
#define rs rt<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef unsigned long long ull;
typedef long long ll;
typedef double db;
const db E=2.718281828;
const db PI=acos(-1.0);
const ll INF=(1LL<<60);
const int inf=(1<<30);
const db ESP=1e-9;
const int mod=(int)1e9+7;
const int N=(int)1e6+10;

int n,m,q;
class LINK
{
public:
	struct EDGE
	{
		int to,next;
	}edge[N<<1];
	int etot;
	int head[N];
	void Init(int n)
	{
		etot=0;
		for(int i=0;i<=n;++i)
			head[i]=0;
	}
	void add(int from,int to)
	{
		++etot;
		edge[etot].to=to;
		edge[etot].next=head[from];
		head[from]=etot;
	}//for(int i=head[u];i;i=edge[i].next)
}G,T;

multiset<int>mset[100010];
int a[N];
class TARJAN
{
public:
	int deep,dfn[N],low[N],fa[N];
	int sccn;
	bool in[N];
	void build(int u,int v)
	{
		++sccn;
		for(int i=v;i!=fa[u];i=fa[i])
		{
			T.add(i,sccn);
			T.add(sccn,i);
		}
	}
	void Tarjan(int u)
	{
		dfn[u]=++deep;
		low[u]=deep;
		in[u]=true;
		for(int i=G.head[u];i;i=G.edge[i].next)
		{
			int to=G.edge[i].to;
			if(!dfn[to])
			{
				fa[to]=u;
				Tarjan(to);
				low[u]=min(low[u],low[to]);
			}
			else if(in[to])
				low[u]=min(low[u],low[to]);
			if(low[to]>dfn[u])T.add(u,to),T.add(to,u);//添加桥边
		}
		for(int i=G.head[u];i;i=G.edge[i].next)
		{
			int to=G.edge[i].to;
			if(fa[to]!=u&&dfn[u]<dfn[to])
				build(u,to);
		}
	}
	void dfs(int u,int f)
	{
		for(int i=T.head[u];i;i=T.edge[i].next)
		{
			int to=T.edge[i].to;
			if(to==f)continue;
			if(u>n)mset[u].insert(a[to]);
			dfs(to,u);
		}
		if(u>n)a[u]=*mset[u].begin();
	}
}Taj;

int Query(int L,int R,int l,int r,int rt);//查询区间和

int LCA;
class TREECUT//树链剖分
{
public:
	int DFN;
	int f[N],d[N],sz[N],hson[N],top[N],dfn[N],real[N];
	void dfs1(int u,int fa,int deep)
	{
		sz[u]=1;
		d[u]=deep;
		f[u]=fa;
		for(int i=T.head[u];i;i=T.edge[i].next)
		{
			int to=T.edge[i].to;
			if(to==fa)continue;
			dfs1(to,u,deep+1);
			sz[u]+=sz[to];
			if(sz[to]>sz[hson[u]])hson[u]=to;
		}
	}
	void dfs2(int u,int t)
	{
		top[u]=t;
		dfn[u]=++DFN;
		real[DFN]=u;
		if(!hson[u])return;
		dfs2(hson[u],t);
		for(int i=T.head[u];i;i=T.edge[i].next)
		{
			int to=T.edge[i].to;
			if(to==f[u]||to==hson[u])continue;
			dfs2(to,to);
		}
	}
	int get_min(int x,int y)
	{
		int ans=inf,fx=top[x],fy=top[y];
		while(fx!=fy)//两点不在同一条重链
		{
			if(d[fx]>=d[fy])
			{
				ans=min(ans,Query(dfn[fx],dfn[x],1,Taj.sccn,1));
				x=f[fx],fx=top[x];
			}
			else
			{
				ans=min(ans,Query(dfn[fy],dfn[y],1,Taj.sccn,1));
				y=f[fy],fy=top[y];
			}
		}
		if(dfn[x]<=dfn[y])
			ans=min(ans,Query(dfn[x],dfn[y],1,Taj.sccn,1)),LCA=x;
		else
			ans=min(ans,Query(dfn[y],dfn[x],1,Taj.sccn,1)),LCA=y;
		return ans;
	}
}TREE;

int min_[N<<2];
void up(int rt)
{
	min_[rt]=min(min_[ls],min_[rs]);
}
void Build(int l,int r,int rt)
{
	min_[rt]=inf;
	if(l==r)
	{
		min_[rt]=a[TREE.real[l]];
		return;
	}
	int mid=(l+r)>>1;

	Build(l,mid,rt<<1);
	Build(mid+1,r,rt<<1|1);
	up(rt);
}
void update_dot(int pos,int val,int l,int r,int rt)
{
	if(pos>r||pos<l)return;
	if(l==r)
	{
		min_[rt]=val;
		return;
	}

	int mid=(l+r)>>1;
	if(pos<=mid)
		update_dot(pos,val,l,mid,rt<<1);
	else
		update_dot(pos,val,mid+1,r,rt<<1|1);
	up(rt);
}
int Query(int L,int R,int l,int r,int rt)//查询区间和
{
	if(L>R)return inf;
	if(L<=l&&r<=R)return min_[rt];
	int mid=(l+r)>>1;
	int ans=inf;
	if(L<=mid) ans=min(Query(L,R,l,mid,rt<<1),ans);
	if(R> mid) ans=min(Query(L,R,mid+1,r,rt<<1|1),ans);
	return ans;
}

signed main()
{
	sc("%d%d%d",&n,&m,&q);
	for(int i=1;i<=n;++i)sc("%d",&a[i]);
	for(int i=1;i<=m;++i)
	{
		int u,v;
		sc("%d%d",&u,&v);
		G.add(u,v);
		G.add(v,u);
	}
	Taj.sccn=n;
	Taj.Tarjan(1);
	Taj.dfs(1,0);
	TREE.dfs1(1,0,1);
	TREE.dfs2(1,1);
	Build(1,Taj.sccn,1);
	for(int i=1;i<=q;++i)
	{
		char temp[5];
		int x,y;
		sc("%s%d%d",temp,&x,&y);
		if(temp[0]=='A')
		{
			int ans=TREE.get_min(x,y);
//			TREE.get_min(x,y);
//			if(LCA>n)
//			{
//				int pre=a[TREE.f[LCA]];
//				mset[LCA].erase(mset[LCA].find(pre));
//				mset[LCA].insert(a[TREE.f[LCA]]);
//				update_dot(TREE.dfn[LCA],*mset[LCA].begin(),1,Taj.sccn,1);
//				a[LCA]=*mset[LCA].begin();
//			}
			if(LCA>n)
				ans=min(ans,a[TREE.f[LCA]]);
			pr("%d\n",ans);
		}
		else
		{
			int fa=TREE.f[x];
			if(fa>n)
			{
				int pre=a[x];
				mset[fa].erase(mset[fa].find(pre));
				mset[fa].insert(y);
				update_dot(TREE.dfn[fa],*mset[fa].begin(),1,Taj.sccn,1);
				a[fa]=*mset[fa].begin();
			}
			a[x]=y;
			update_dot(TREE.dfn[x],y,1,Taj.sccn,1);
		}
	}
	return 0;
}

/**************************************************************************************/


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

inline int gi()
{
	char c = getchar();
	while (c < '0' || c > '9') c = getchar();
	int sum = 0;
	while ('0' <= c && c <= '9') sum = sum * 10 + c - 48, c = getchar();
	return sum;
}

inline char gc()
{
	char c = getchar();
	while (c < 'A' || c > 'Z') c = getchar();
	return c;
}

const int maxn = 100005;

int n, m, q, w[maxn << 1];

struct edge
{
	int to, next;
} e[maxn << 1];
int h[maxn], tot;

inline void add(int u, int v)
{
	e[++tot] = (edge) {v, h[u]}; h[u] = tot;
	e[++tot] = (edge) {u, h[v]}; h[v] = tot;
}

vector<int> to[maxn << 1];
int cnt, dep[maxn << 1], siz[maxn << 1], son[maxn << 1], ord[maxn << 1], dfn[maxn << 1], low[maxn << 1], Time, fa[maxn << 1], top[maxn << 1];

struct
{
	priority_queue<int, vector<int>, greater<int> > q1, q2;
	int Top()
	{
		while (!q2.empty() && q1.top() == q2.top()) q1.pop(), q2.pop();
		return q1.top();
	}
	void insert(int x) {q1.push(x);}
	void erase(int x) {q2.push(x);}
} val[maxn];

void dfs1(int u)
{
	dep[u] = dep[fa[u]] + 1; siz[u] = 1;
	for (int v : to[u])
		if (v != fa[u]) {
			fa[v] = u; dfs1(v);
			siz[u] += siz[v];
			if (siz[v] > siz[son[u]]) son[u] = v;
			if (u > n) val[u - n].insert(w[v]);
		}
	if (u > n) w[u] = val[u - n].Top();
}

void dfs2(int u)
{
	ord[dfn[u] = ++Time] = u;
	if (son[u]) top[son[u]] = top[u], dfs2(son[u]);
	else low[top[u]] = Time;

	for (int v : to[u])
		if (v != fa[u] && v != son[u]) top[v] = v, dfs2(v);
}

int rt[maxn << 1], Min[maxn << 3], lch[maxn << 3], rch[maxn << 3];

#define mid ((l + r) >> 1)

void build(int &s, int l, int r)
{
	s = ++tot;
	if (s > 2e5 * 4) puts("fuck you"), exit(0);
	if (l == r) return Min[s] = w[ord[l]], void();
	build(lch[s], l, mid);
	build(rch[s], mid + 1, r);
	Min[s] = min(Min[lch[s]], Min[rch[s]]);
}

void modify(int &s, int l, int r, int p)
{
	if (l == r) return Min[s] = w[ord[l]], void();
	if (p <= mid) modify(lch[s], l, mid, p);
	else modify(rch[s], mid + 1, r, p);
	Min[s] = min(Min[lch[s]], Min[rch[s]]);
}

int query(int s, int l, int r, int ql, int qr)
{
	if (ql <= l && r <= qr) return Min[s];
	if (qr <= mid) return query(lch[s], l, mid, ql, qr);
	else if (ql > mid) return query(rch[s], mid + 1, r, ql, qr);
	else return min(query(lch[s], l, mid, ql, qr), query(rch[s], mid + 1, r, ql, qr));
}

void modify(int v, int u)
{
	if (fa[u]) val[fa[u] - n].erase(w[u]), val[fa[u] - n].insert(v), w[fa[u]] = val[fa[u] - n].Top();
	w[u] = v;
	modify(rt[top[u]], dfn[top[u]], low[top[u]], dfn[u]);
	if (fa[u]) u = fa[u], modify(rt[top[u]], dfn[top[u]], low[top[u]], dfn[u]);
}

int query(int u, int v)
{
	int ans = 1e9;
	while (top[u] != top[v]) {
		if (dep[top[u]] > dep[top[v]]) ans = min(ans, query(rt[top[u]], dfn[top[u]], low[top[u]], dfn[top[u]], dfn[u])), u = fa[top[u]];
		else ans = min(ans, query(rt[top[v]], dfn[top[v]], low[top[v]], dfn[top[v]], dfn[v])), v = fa[top[v]];
	}
	if (dfn[u] > dfn[v]) swap(u, v);
	ans = min(ans, query(rt[top[v]], dfn[top[v]], low[top[v]], dfn[u], dfn[v]));
	if (u > n) ans = min(ans, w[fa[u]]);
	return ans;
}

namespace Tarjan
{

	int dfn[maxn], low[maxn], Time, stk[maxn], top;

	void dfs(int u)
	{
		dfn[u] = low[u] = ++Time;
		stk[++top] = u;
		for (int i = h[u], v; v = e[i].to, i; i = e[i].next)
			if (!dfn[v]) {
				dfs(v);
				low[u] = min(low[u], low[v]);
				if (dfn[u] == low[v]) {
					++cnt;
					while (stk[top + 1] != v)
						to[stk[top]].push_back(cnt), to[cnt].push_back(stk[top]), --top;
					to[u].push_back(cnt), to[cnt].push_back(u);
				}
			} else low[u] = min(low[u], dfn[v]);
	}

}

int main()
{
	n = gi(); m = gi(); q = gi();
	for (int i = 1; i <= n; ++i) w[i] = gi();
	for (int i = 1; i <= m; ++i) add(gi(), gi());

	cnt = n;
	for (int i = 1; i <= n; ++i)
		if (!Tarjan::dfn[i]) Tarjan::dfs(i);

	for (int i = 1; i <= cnt; ++i)
		if (!fa[i]) dfs1(i);
	Time = 0;
	for (int i = 1; i <= cnt; ++i)
		if (!top[i]) top[i] = i, dfs2(i);

	tot = 0;
	for (int i = 1; i <= cnt; ++i)
		if (top[i] == i) build(rt[i], dfn[i], low[i]);

	for (int i = 1; i <= q; ++i) {
		char c = gc();
		if (c == 'C') modify(gi(), gi());
		else printf("%d\n", query(gi(), gi()));
	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,m,q,w[N],dfn[N],low[N],st[N],tp,k,cnt,fa[N],dep[N],son[N],sz[N],top[N],ar[N],tr[N<<2];
vector<int>g[N],e[N];
multiset<int>s[N];
void tarjan(int u)
{
	dfn[u]=low[u]=++cnt;
	st[++tp]=u;
	for(auto v:g[u])
	{
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
			if(low[v]==dfn[u])
			{
				k++;
				for(int x=0;x!=v;tp--)
				{
					x=st[tp];
					e[k].push_back(x);
					e[x].push_back(k);
				}
				e[k].push_back(u);
				e[u].push_back(k);
			}
		}
		else
			low[u]=min(low[u],dfn[v]);
	}
}
void dfs(int u,int f)
{
	fa[u]=f,dep[u]=dep[f]+1,sz[u]=1;
	for(auto v:e[u])
	{
		if(v==f)
			continue;
		dfs(v,u);
		sz[u]+=sz[v];
		if(sz[son[u]]<sz[v])
			son[u]=v;
	}
}
void dfs2(int u,int f,int tp)
{
	dfn[u]=++cnt,top[u]=tp,ar[cnt]=u;
	if(son[u])
		dfs2(son[u],u,tp);
	for(auto v:e[u])
	{
		if(v==f||v==son[u])
			continue;
		dfs2(v,u,v);
	}
}
void build(int k,int l,int r)
{
	if(l==r)
	{
		tr[k]=w[ar[l]];
		return;
	}
	int mid=l+r>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	tr[k]=min(tr[k<<1],tr[k<<1|1]);
}
void upd(int k,int l,int r,int x,int v)
{
	if(l==r)
	{
		tr[k]=v;
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) upd(k<<1,l,mid,x,v);
	else upd(k<<1|1,mid+1,r,x,v);
	tr[k]=min(tr[k<<1],tr[k<<1|1]);
}
int query(int k,int l,int r,int a,int b)
{
	if(l==a&&r==b)
		return tr[k];
	int mid=l+r>>1;
	if(b<=mid) return query(k<<1,l,mid,a,b);
	else if(a>mid) return query(k<<1|1,mid+1,r,a,b);
	else return min(query(k<<1,l,mid,a,mid),query(k<<1|1,mid+1,r,mid+1,b));
}
int main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>q;
	for(int i=1;i<=n;i++)
		cin>>w[i];
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	k=n;
	tarjan(1);
	dfs(1,0);
	cnt=0;
	dfs2(1,0,1);
	for(int i=1;i<=n;i++)
		if(fa[i])
			s[fa[i]].insert(w[i]);
	for(int i=n+1;i<=k;i++)
		w[i]=*s[i].begin();
	build(1,1,k);
	while(q--)
	{
		char op;
		int x,y;
		cin>>op>>x>>y;
		if(op=='C')
		{
			upd(1,1,k,dfn[x],y);
			if(fa[x])
			{
				int u=fa[x];
				s[u].erase(s[u].lower_bound(w[x]));
				s[u].insert(y);
				w[u]=*s[u].begin();
				upd(1,1,k,dfn[u],w[u]);
			}
			w[x]=y;
		}
		else
		{
			int ans=1e9;
			while(top[x]!=top[y])
			{
				if(dep[top[x]]<dep[top[y]])
					swap(x,y);
				ans=min(ans,query(1,1,k,dfn[top[x]],dfn[x]));
				x=fa[top[x]];
			}
			if(dfn[x]>dfn[y])
				swap(x,y);
			ans=min(ans,query(1,1,k,dfn[x],dfn[y]));
			if(x>n)
				ans=min(ans,w[fa[x]]);
			printf("%d\n",ans);
		}
	}
	return 0;
}
/////
///


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){
	register int res=0;
	register char c=getchar(),f=1;
	while(c<48||c>57){if(c=='-')f=0;c=getchar();}
	while(c>=48&&c<=57)res=(res<<3)+(res<<1)+(c&15),c=getchar();
	return f?res:-res;
}
inline char getc(){
	register char c=getchar();
	while(c<65||c>90)c=getchar();
	return c;
}

const int N=1e5+5;
int n,m,q,a[N];
vector<int> G[N],T[N*2];
int dfn[N*2],low[N],sta[N],tp=0,tot=0,totv;
multiset<int> c[N*2];
void dfs(int u,int fa){
	sta[++tp]=u,dfn[u]=low[u]=++tot;
	for(auto v:G[u])if(v!=fa){
		if(!dfn[v]){
			dfs(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]){
				T[u].push_back(++totv);
				int z;
				do{
					z=sta[tp--];
					T[totv].push_back(z);
					c[totv].insert(a[z]);
				}while(z!=v);
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}

int fa[N],sz[N],son[N],dep[N],val[N],top[N];
void dfs1(int u){
	sz[u]=1;
	for(auto v:T[u])if(v!=fa[u]){
		fa[v]=u,dep[v]=dep[u]+1;
		dfs1(v),sz[u]+=sz[v];
		if(sz[son[u]]<sz[v])son[u]=v;
	}
}
void dfs2(int u,int tp){
	dfn[u]=++tot,top[u]=tp;
	val[tot]=u<=n?a[u]:*c[u].begin();
	if(son[u])dfs2(son[u],tp);
	for(auto v:T[u])if(v!=fa[u]&&v!=son[u])
		dfs2(v,v);
}

#define lc (x<<1)
#define rc (x<<1|1)
#define mid ((l+r)>>1)
int mn[N*8];
void build(int x,int l,int r){
	if(l==r){mn[x]=val[l];return;}
	build(lc,l,mid),build(rc,mid+1,r);
	mn[x]=min(mn[lc],mn[rc]);
}
void update(int x,int l,int r,int pos,int val){
	if(l==r){mn[x]=val;return;}
	if(pos<=mid)update(lc,l,mid,pos,val);
	else update(rc,mid+1,r,pos,val);
	mn[x]=min(mn[lc],mn[rc]);
}
int query(int x,int l,int r,int le,int ri){
	if(l==le&&r==ri)return mn[x];
	int res=1e9;
	if(le<=mid)res=min(res,query(lc,l,mid,le,min(mid,ri)));
	if(ri>mid)res=min(res,query(rc,mid+1,r,max(mid+1,le),ri));
	return res;
}

int op,x,y;
int main(){
	n=read(),m=read(),q=read();
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=1;i<=m;++i){
		x=read(),y=read();
		G[x].push_back(y);
		G[y].push_back(x);
	}
	totv=n,tot=0,dfs(1,0);
	memset(dfn+1,0,sizeof(int)*n);
	tot=0,dfs1(1),dfs2(1,1);
	build(1,1,totv);
	while(q--){
		op=getc(),x=read(),y=read();
		if(op=='C'){
			update(1,1,n,dfn[x],y);
			if(fa[x]){
				c[fa[x]].erase(c[fa[x]].find(a[x]));
				if(c[fa[x]].empty()||y<*c[fa[x]].begin())
					update(1,1,totv,dfn[fa[x]],y);
				c[fa[x]].insert(a[x]=y);
			}
		}
		else{
			int res=1e9;
			while(top[x]!=top[y]){
				if(dep[top[x]]<dep[top[y]])swap(x,y);
				res=min(res,query(1,1,totv,dfn[fa[x]],dfn[x]));
				x=fa[top[x]];
			}
			if(dep[x]>dep[y])swap(x,y);
			res=min(res,query(1,1,totv,dfn[x],dfn[y]));
			if(x>n)res=min(res,query(1,1,totv,dfn[fa[x]],dfn[fa[x]]));
			printf("%d\n",res);
		}
	}
}


#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#include <cstdio>//sprintf islower isupper
#include <cstdlib>//malloc  exit strcat itoa system("cls")
#include <iostream>//pair
#include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin);
#include <bitset>
//#include <map>
//#include<unordered_map>
#include <vector>
#include <stack>
#include <set>
#include <string.h>//strstr substr strcat
#include <string>
#include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
#include <cmath>
#include <deque>
#include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
#include <vector>//emplace_back
//#include <math.h>
#include <cassert>
#include <iomanip>
//#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
#include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
//******************
clock_t __START,__END;
double __TOTALTIME;
void _MS(){__START=clock();}
void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;}
//***********************
#define rint register int
#define fo(a,b,c) for(rint a=b;a<=c;++a)
#define fr(a,b,c) for(rint a=b;a>=c;--a)
#define mem(a,b) memset(a,b,sizeof(a))
#define pr printf
#define sc scanf
#define ls rt<<1
#define rs rt<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef unsigned long long ull;
typedef long long ll;
typedef double db;
const db E=2.718281828;
const db PI=acos(-1.0);
const ll INF=(1LL<<60);
const int inf=(1<<30);
const db ESP=1e-9;
const int mod=(int)1e9+7;
const int N=(int)1e5+10;

int n,m,q;
class LINK
{
public:
	struct EDGE
	{
		int to,next;
	}edge[N<<1];
	int etot;
	int head[N];
	void Init(int n)
	{
		etot=0;
		for(int i=0;i<=n;++i)
			head[i]=0;
	}
	void add(int from,int to)
	{
		++etot;
		edge[etot].to=to;
		edge[etot].next=head[from];
		head[from]=etot;
	}//for(int i=head[u];i;i=edge[i].next)
}G,T;

multiset<int>mset[N];
int a[N];
class TARJAN
{
public:
	int deep,dfn[N],low[N],fa[N];
	int sccn;
	bool in[N];
	void build(int u,int v)
	{
		++sccn;
		for(int i=v;i!=fa[u];i=fa[i])
		{
			T.add(i,sccn);
			T.add(sccn,i);
		}
	}
	void Tarjan(int u)
	{
		dfn[u]=++deep;
		low[u]=deep;
		in[u]=true;
		for(int i=G.head[u];i;i=G.edge[i].next)
		{
			int to=G.edge[i].to;
			if(!dfn[to])
			{
				fa[to]=u;
				Tarjan(to);
				low[u]=min(low[u],low[to]);
			}
			else if(in[to])
				low[u]=min(low[u],low[to]);
			if(low[to]>dfn[u])T.add(u,to),T.add(to,u);//添加桥边
		}
		for(int i=G.head[u];i;i=G.edge[i].next)
		{
			int to=G.edge[i].to;
			if(fa[to]!=u&&dfn[u]<dfn[to])
				build(u,to);
		}
	}
	void dfs(int u,int f)
	{
		for(int i=T.head[u];i;i=T.edge[i].next)
		{
			int to=T.edge[i].to;
			if(to==f)continue;
			if(u>n)mset[u].insert(a[to]);
			dfs(to,u);
		}
		if(u>n)a[u]=*mset[u].begin();
	}
}Taj;

int Query(int L,int R,int l,int r,int rt);//查询区间和

int LCA;
class TREECUT//树链剖分
{
public:
	int DFN;
	int f[N],d[N],sz[N],hson[N],top[N],dfn[N],real[N];
	void dfs1(int u,int fa,int deep)
	{
		sz[u]=1;
		d[u]=deep;
		f[u]=fa;
		for(int i=T.head[u];i;i=T.edge[i].next)
		{
			int to=T.edge[i].to;
			if(to==fa)continue;
			dfs1(to,u,deep+1);
			sz[u]+=sz[to];
			if(sz[to]>sz[hson[u]])hson[u]=to;
		}
	}
	void dfs2(int u,int t)
	{
		top[u]=t;
		dfn[u]=++DFN;
		real[DFN]=u;
		if(!hson[u])return;
		dfs2(hson[u],t);
		for(int i=T.head[u];i;i=T.edge[i].next)
		{
			int to=T.edge[i].to;
			if(to==f[u]||to==hson[u])continue;
			dfs2(to,to);
		}
	}
	int get_min(int x,int y)
	{
		int ans=inf,fx=top[x],fy=top[y];
		while(fx!=fy)//两点不在同一条重链
		{
			if(d[fx]>=d[fy])
			{
				ans=min(ans,Query(dfn[fx],dfn[x],1,Taj.sccn,1));
				x=f[fx],fx=top[x];
			}
			else
			{
				ans=min(ans,Query(dfn[fy],dfn[y],1,Taj.sccn,1));
				y=f[fy],fy=top[y];
			}
		}
		if(dfn[x]<=dfn[y])
			ans=min(ans,Query(dfn[x],dfn[y],1,Taj.sccn,1)),LCA=x;
		else
			ans=min(ans,Query(dfn[y],dfn[x],1,Taj.sccn,1)),LCA=y;
		return ans;
	}
}TREE;

int min_[N];
void up(int rt)
{
	min_[rt]=min(min_[ls],min_[rs]);
}
void Build(int l,int r,int rt)
{
	min_[rt]=inf;
	if(l==r)
	{
		min_[rt]=a[TREE.real[l]];
		return;
	}
	int mid=(l+r)>>1;

	Build(l,mid,rt<<1);
	Build(mid+1,r,rt<<1|1);
	up(rt);
}
void update_dot(int pos,int val,int l,int r,int rt)
{
	if(pos>r||pos<l)return;
	if(l==r)
	{
		min_[rt]=val;
		return;
	}

	int mid=(l+r)>>1;
	if(pos<=mid)
		update_dot(pos,val,l,mid,rt<<1);
	else
		update_dot(pos,val,mid+1,r,rt<<1|1);
	up(rt);
}
int Query(int L,int R,int l,int r,int rt)//查询区间和
{
	if(L>R)return inf;
	if(L<=l&&r<=R)return min_[rt];
	int mid=(l+r)>>1;
	int ans=inf;
	if(L<=mid) ans=min(Query(L,R,l,mid,rt<<1),ans);
	if(R> mid) ans=min(Query(L,R,mid+1,r,rt<<1|1),ans);
	return ans;
}

signed main()
{
	sc("%d%d%d",&n,&m,&q);
	for(int i=1;i<=n;++i)sc("%d",&a[i]);
	for(int i=1;i<=m;++i)
	{
		int u,v;
		sc("%d%d",&u,&v);
		G.add(u,v);
		G.add(v,u);
	}
	Taj.sccn=n;
	Taj.Tarjan(1);
	Taj.dfs(1,0);
	TREE.dfs1(1,0,1);
	TREE.dfs2(1,1);
	Build(1,Taj.sccn,1);
	for(int i=1;i<=q;++i)
	{
		char temp[5];
		int x,y;
		sc("%s%d%d",temp,&x,&y);
		if(temp[0]=='A')
		{
			int ans=TREE.get_min(x,y);
//			TREE.get_min(x,y);
//			if(LCA>n)
//			{
//				int pre=a[TREE.f[LCA]];
//				mset[LCA].erase(mset[LCA].find(pre));
//				mset[LCA].insert(a[TREE.f[LCA]]);
//				update_dot(TREE.dfn[LCA],*mset[LCA].begin(),1,Taj.sccn,1);
//				a[LCA]=*mset[LCA].begin();
//			}
			if(LCA>n)
				ans=min(ans,a[TREE.f[LCA]]);
			pr("%d\n",ans);
		}
		else
		{
			int fa=TREE.f[x];
			if(fa>n)
			{
				int pre=a[x];
				mset[fa].erase(mset[fa].find(pre));
				mset[fa].insert(y);
				update_dot(TREE.dfn[fa],*mset[fa].begin(),1,Taj.sccn,1);
				a[fa]=*mset[fa].begin();
			}
			a[x]=y;
			update_dot(TREE.dfn[x],y,1,Taj.sccn,1);
		}
	}
	return 0;
}

/**************************************************************************************/


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<stack>
#include<vector>
using namespace std;
#define ls (x<<1)
#define rs (x<<1|1)
const int N=1e5+9,M=2e6+9,INF=0x7f7f7f7f;
int dfn[M],low[N],ind,fa[M],top[M],siz[M],n,m,a[M],w[M],son[M];
char op[3];
int q,cnt,num,dep[M],id[M];
stack<int> stk;
multiset<int> S[M];
vector<int> g[N],G[M];
int val[M<<2];

void Tarjan(int u)
{
	low[u]=dfn[u]=++ind;
	stk.push(u);
	for(auto v:g[u])
	{
		if(!dfn[v])
		{
			Tarjan(v);
			low[u]=min(low[u],low[v]);
			if(low[v]==dfn[u])
			{
				++cnt;
				for(int x=0;x!=v;stk.pop())
				{
					x=stk.top();
					G[cnt].push_back(x);
					G[x].push_back(cnt);
				}
				G[u].push_back(cnt);
				G[cnt].push_back(u);
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}

void dfs1(int u,int f)
{
	fa[u]=f;
	siz[u]=1;
	dep[u]=dep[f]+1;
	for(auto v:G[u])
	{
		if(v==fa[u]) continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[v]>siz[son[u]]) son[u]=v;
	}
}

void dfs2(int u,int topf)
{
	top[u]=topf;
	dfn[u]=++ind;
	w[ind]=a[u];
	id[ind]=u;
	if(!son[u]) return;
	dfs2(son[u],topf);
	for(auto v:G[u])
	{
		if(v==fa[u]||v==son[u]) continue;
		dfs2(v,v);
	}
}

inline void update(int x)
{
	val[x]=min(val[ls],val[rs]);
}

void build(int x,int l,int r)
{
	if(l==r)
	{
		val[x]=a[id[l]];
		return;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	update(x);
}

int query(int x,int l,int r,int L,int R)
{
	if(L<=l&&r<=R) return val[x];
	int mid=(l+r)>>1,res=INF;
	if(L<=mid) res=min(res,query(ls,l,mid,L,R));
	if(R>mid) res=min(res,query(rs,mid+1,r,L,R));
	return res;
}

void change(int x,int l,int r,int pos,int c)
{
	if(l==r)
	{
		val[x]=c;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) change(ls,l,mid,pos,c);
	if(pos>mid) change(rs,mid+1,r,pos,c);
	update(x);
}

int main()
{
	scanf("%d%d%d",&n,&m,&q);
	cnt=n;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	Tarjan(1);
	dfs1(1,0);
	ind=0;
	dfs2(1,1);
	for(int i=1;i<=n;i++) if(fa[i]) S[fa[i]].insert(a[i]);
	for(int i=n+1;i<=cnt;i++) a[i]=*S[i].begin();
	// memset(dfn,0,sizeof dfn);
	build(1,1,cnt);
	// for(int i=1;i<=cnt;i++) printf("%d ",a[i]);
	while(q--)
	{
		scanf("%s",op+1);
		int x,y;
		scanf("%d%d",&x,&y);
		if(op[1]=='A')
		{
			int res=INF;
			while(top[x]!=top[y])
			{
				if(dep[top[x]]<dep[top[y]]) swap(x,y);
				res=min(res,query(1,1,cnt,dfn[top[x]],dfn[x]));
				x=fa[top[x]];
			}
			if(dfn[x]<dfn[y]) swap(x,y);
			res=min(res,query(1,1,cnt,dfn[y],dfn[x]));
			if(y>n) res=min(res,a[fa[y]]);
			printf("%d\n",res);
		}

		else
		{
			change(1,1,cnt,dfn[x],y);
			if(!fa[x]) {a[x]=y;continue;}
			S[fa[x]].erase(S[fa[x]].find(a[x]));
			S[fa[x]].insert(y);
			a[fa[x]]=*S[fa[x]].begin();
			change(1,1,cnt,dfn[fa[x]],a[fa[x]]);
			a[x]=y;
		}
	}
	return 0;
}


/*input
3 3 3
1
2
3
1 2
2 3
1 3
A 2 3
C 1 5
A 2 3
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define REP(i,j,k)     for(int i = j ; i < k ; ++i)
#define RREP(i,j,k)    for(int i = j ; i >=k ; --i)
#define A    first
#define B    second
#define mp   make_pair
#define pb   emplace_back
#define PII pair<int , int>
#define MEM(i,j)   memset(i , j , sizeof i)
#define ALL(i)     i.begin() , i.end()
#define DBGG(i,j)     cout << i << " " << j << endl
#define DB4(i,j,k,l)  cout << i << " " << j << " " << k << " " << l << endl
#define IOS cin.tie() , cout.sync_with_stdio(0)
// #define endl "\n"
///------------------------------------------------------------
#define MAX 300900
#define INF 0x3f3f3f3f
#define mid ((l + r) >> 1)
#define ls (now << 1)
#define rs (now << 1 | 1)

int n , m , k , x[MAX];
int cut[MAX] , bcc[MAX] , bccpo;
struct Decomposition{
	vector<int> v[MAX];
	multiset<int> dotval[MAX];
	int sml[MAX * 4];
	int pat[MAX] , son[MAX] , siz[MAX] , dep[MAX];
	int top[MAX] , id[MAX] , idpo = 0;
	void DFS1(int now , int fa , int deep){
		pat[now] = fa;
		dep[now] = deep;
		son[now] = 0;
		siz[now] = 1;
		for(auto to : v[now]){
			if(to == fa) continue;
			DFS1(to , now , deep + 1);
			siz[now] += siz[to];
			if(siz[to] > siz[son[now]]) son[now] = to;
		}
	}
	void DFS2(int now , int fa , int root){
		id[now] = ++idpo;
		// DB4("id[" , now , "] = " , idpo);
		top[now] = root;
		if(son[now]) DFS2(son[now] , now , root);
		for(auto to : v[now]){
			if(to == fa || to == son[now]) continue;
			DFS2(to , now , to);
		}
	}
	void update(int now , int l , int r , int k , int v){
		// DB4("update = " , k , v , "");
		if(l == k && r == k) sml[now] = v;
		else {
			if(k <= mid + 0) update(ls , l , mid + 0 , k , v);
			if(mid + 1 <= k) update(rs , mid + 1 , r , k , v);
			sml[now] = min(sml[ls] , sml[rs]);
		}
	}
	int query(int now , int l , int r , int ql , int qr){
		if(ql > qr) swap(ql , qr);
		if(ql <= l && r <= qr) return sml[now];
		else if(qr <= mid + 0) return query(ls , l , mid + 0 , ql , qr);
		else if(mid + 1 <= ql) return query(rs , mid + 1 , r , ql , qr);
		return min(query(ls , l , mid + 0 , ql , qr) , query(rs , mid + 1 , r , ql , qr));
	}
	int update(int dot , int from , int val){
		dotval[dot].erase(dotval[dot].find(from));
		dotval[dot].insert(val);
		update(1 , 1 , idpo , id[dot] , *dotval[dot].begin());
	}
	int query(int a , int b){
		// cout << "in" << endl;
		int t1 = top[a] , t2 = top[b] , ans = INF;
		while(t1 != t2){
			// DB4(a , t1 , b , t2);
			// if(a == 0 && t1 == 0) break;
			if(dep[t1] < dep[t2]) swap(a , b) , swap(t1 , t2);
			ans = min(ans , query(1 , 1 , idpo , id[a] , id[t1]));
			a = pat[t1] , t1 = top[a];
		}
		int tmp = (id[a] < id[b]) ? a : b;
		if(tmp > n) ans = min(ans , x[pat[tmp]]);
		ans = min(ans , query(1 , 1 , idpo , id[a] , id[b]));
		return ans;
	}
	int solveinit(){
		v[0].pb(1);
		DFS1(0 , 0 , 0);
		DFS2(0 , 0 , 0);
		MEM(sml , INF);
		REP(i , 1 , n + 1){
			dotval[i].insert(x[i]);
			dotval[pat[i]].insert(x[i]);
		}
		// REP(i , 1 , bccpo){
		// 	cout << "now i = " << i << " ";
		// 	for(auto to : dotval[i]){
		// 		cout << to << " ";
		// 	} cout << endl;
		// }
		REP(i , 1 , bccpo){
			update(1 , 1 , idpo , id[i] , *dotval[i].begin());
		}
	}
} solver;
struct Tarjan{
	vector<int> v[MAX];
	set<int> cc[MAX];

	int low[MAX] , dep[MAX] , use[MAX];
	stack<PII> sk;
	void DFS(int now , int fa , int deep){
		cut[now] = 0;
		use[now] = 1;
		low[now] = deep;
		dep[now] = deep;
		int son = 0;
		for(auto to : v[now]){
			if(use[to]) low[now] = min(low[now] , dep[to]);
			else {
				sk.push(mp(now , to));
				son ++ , DFS(to , now , deep + 1);
				low[now] = min(low[now] , low[to]);
				if(low[to] >= dep[now]){
					cut[now] = 1;
					while(sk.size()){
						int a = sk.top().A , b = sk.top().B;
						sk.pop();
						cc[bccpo].insert(a);
						bcc[a] = bccpo;
						bcc[b] = bccpo;
						cc[bccpo].insert(b);
						if(now == a && to == b) break;
						if(now == b && to == a) break;
					}
					bccpo ++;
				}
			}
		}
		if(deep == 0) cut[now] = (son >= 2);
	}
	void Build(){
		REP(i , n + 1 , bccpo){
			for(auto to : cc[i]){
				solver.v[i].pb(to);
				solver.v[to].pb(i);
				// DBGG(i , to);
			}
		}
	}
	void solveinit(){
		MEM(use , 0);
		bccpo = n + 1;
		DFS(1 , 0 , 0);
		Build();
	}
} cuter;
int32_t main(){
	cin >> n >> m >> k;
	REP(i , 1 , n + 1){
		cin >> x[i];
	}
	REP(i , 1 , m + 1){
		int a , b; cin >> a >> b;
		cuter.v[a].pb(b) , cuter.v[b].pb(a);
	}

	cuter.solveinit();
	solver.solveinit();

	char ty;
	int a , b;
	REP(i , 1 , k + 1){
		cin >> ty >> a >> b;
		if(ty == 'A') cout << solver.query(a , b) << endl;
		if(ty == 'C'){
			if(cut[a] == 0) solver.update(a , x[a] , b);
			if(cut[a] == 1){
				solver.update(a , x[a] , b);
				solver.update(solver.pat[a] , x[a] , b);
			}
			x[a] = b;
		}
	}
    return 0;
}


/*input
5 6 6
10
40
20
70
30
2 1
1 3
2 3
1 4
1 5
5 4
C 1 50
A 3 1
C 3 60
A 4 1
A 4 3
A 3 4
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define REP(i,j,k)     for(int i = j ; i < k ; ++i)
#define RREP(i,j,k)    for(int i = j ; i >=k ; --i)
#define A    first
#define B    second
#define mp   make_pair
#define pb   emplace_back
#define PII pair<int , int>
#define MEM(i,j)   memset(i , j , sizeof i)
#define ALL(i)     i.begin() , i.end()
#define DBGG(i,j)     cout << i << " " << j << endl
#define DB4(i,j,k,l)  cout << i << " " << j << " " << k << " " << l << endl
#define IOS cin.tie() , cout.sync_with_stdio(0)
// #define endl "\n"
///------------------------------------------------------------
#define MAX 300900
#define INF 0x3f3f3f3f
#define mid ((l + r) >> 1)
#define ls (now << 1)
#define rs (now << 1 | 1)

int n , m , k , x[MAX];
int cut[MAX] , bcc[MAX] , bccpo;
struct Decomposition{
	vector<int> v[MAX];
	multiset<int> dotval[MAX];
	int sml[MAX * 4];
	int pat[MAX] , son[MAX] , siz[MAX] , dep[MAX];
	int top[MAX] , id[MAX] , idpo = 0;
	void DFS1(int now , int fa , int deep){
		pat[now] = fa;
		dep[now] = deep;
		son[now] = 0;
		siz[now] = 1;
		for(auto to : v[now]){
			if(to == fa) continue;
			DFS1(to , now , deep + 1);
			siz[now] += siz[to];
			if(siz[to] > siz[son[now]]) son[now] = to;
		}
	}
	void DFS2(int now , int fa , int root){
		id[now] = ++idpo;
		// DB4("id[" , now , "] = " , idpo);
		top[now] = root;
		if(son[now]) DFS2(son[now] , now , root);
		for(auto to : v[now]){
			if(to == fa || to == son[now]) continue;
			DFS2(to , now , to);
		}
	}
	void update(int now , int l , int r , int k , int v){
		// if(now == 1) DB4("update = " , k , v , "");
		if(l == k && r == k) sml[now] = v;
		else {
			if(k <= mid + 0) update(ls , l , mid + 0 , k , v);
			if(mid + 1 <= k) update(rs , mid + 1 , r , k , v);
			sml[now] = min(sml[ls] , sml[rs]);
		}
	}
	int query(int now , int l , int r , int ql , int qr){
		if(ql > qr) swap(ql , qr);
		if(ql <= l && r <= qr) return sml[now];
		else if(qr <= mid + 0) return query(ls , l , mid + 0 , ql , qr);
		else if(mid + 1 <= ql) return query(rs , mid + 1 , r , ql , qr);
		return min(query(ls , l , mid + 0 , ql , qr) , query(rs , mid + 1 , r , ql , qr));
	}
	int update(int dot , int from , int val){
		dotval[dot].erase(dotval[dot].find(from));
		dotval[dot].insert(val);
		update(1 , 1 , idpo , id[dot] , *dotval[dot].begin());
	}
	int query(int a , int b){
		// cout << "in" << endl;
		int t1 = top[a] , t2 = top[b] , ans = INF;
		while(t1 != t2){
			// DB4(a , t1 , b , t2);
			// if(a == 0 && t1 == 0) break;
			if(dep[t1] < dep[t2]) swap(a , b) , swap(t1 , t2);
			ans = min(ans , query(1 , 1 , idpo , id[a] , id[t1]));
			a = pat[t1] , t1 = top[a];
		}
		int tmp = (id[a] < id[b]) ? a : b;
		if(tmp > n) ans = min(ans , x[pat[tmp]]);
		ans = min(ans , query(1 , 1 , idpo , id[a] , id[b]));
		return ans;
	}
	int print(int now , int l , int r){
		if(l == r) cout << sml[now] << " ";
		else print(ls , l , mid + 0) , print(rs , mid + 1 , r);
	}
	int solveinit(){
		v[0].pb(1);
		DFS1(0 , 0 , 0);
		DFS2(0 , 0 , 0);
		MEM(sml , INF);
		REP(i , 1 , n + 1){
			dotval[i].insert(x[i]);
			dotval[pat[i]].insert(x[i]);
		}
		// REP(i , 1 , bccpo){
		// 	cout << "now i " << i << " = ";
		// 	for(auto to : dotval[i]){
		// 		cout << to << " ";
		// 	} cout << endl;
		// }
		REP(i , 1 , bccpo){
			update(1 , 1 , idpo , id[i] , *dotval[i].begin());
		}
	}
} solver;
struct Tarjan{
	vector<int> v[MAX];
	set<int> cc[MAX];

	int low[MAX] , dep[MAX] , use[MAX];
	stack<PII> sk;
	void DFS(int now , int fa , int deep){
		cut[now] = 0;
		use[now] = 1;
		low[now] = deep;
		dep[now] = deep;
		int son = 0;
		for(auto to : v[now]){
			if(use[to]) low[now] = min(low[now] , dep[to]);
			else {
				sk.push(mp(now , to));
				son ++ , DFS(to , now , deep + 1);
				low[now] = min(low[now] , low[to]);
				if(low[to] >= dep[now]){
					cut[now] = 1;
					while(sk.size()){
						int a = sk.top().A , b = sk.top().B;
						sk.pop();
						cc[bccpo].insert(a);
						bcc[a] = bccpo;
						bcc[b] = bccpo;
						cc[bccpo].insert(b);
						if(now == a && to == b) break;
						if(now == b && to == a) break;
					}
					bccpo ++;
				}
			}
		}
		if(deep == 0) cut[now] = (son >= 2);
	}
	void Build(){
		REP(i , n + 1 , bccpo){
			for(auto to : cc[i]){
				solver.v[i].pb(to);
				solver.v[to].pb(i);
				// DBGG(i , to);
			}
		}
	}
	void solveinit(){
		MEM(use , 0);
		bccpo = n + 1;
		DFS(1 , 0 , 0);
		Build();
	}
} cuter;
int32_t main(){
	cin >> n >> m >> k;
	REP(i , 1 , n + 1){
		cin >> x[i];
	}
	REP(i , 1 , m + 1){
		int a , b; cin >> a >> b;
		cuter.v[a].pb(b) , cuter.v[b].pb(a);
	}

	cuter.solveinit();
	solver.solveinit();

	// REP(i , 1 , n + 1) if(cut[i]) DBGG("find one = " , i);

	char ty;
	int a , b;
	REP(i , 1 , k + 1){
		cin >> ty >> a >> b;
		if(ty == 'A') cout << solver.query(a , b) << endl;
		if(ty == 'C'){
			solver.update(a , x[a] , b);
			solver.update(solver.pat[a] , x[a] , b);
			x[a] = b;
		}
		// cout << "result = "; solver.print(1 , 1 , solver.idpo); cout << endl;
	}
    return 0;
}


/*input
5 6 6
10
40
20
70
30
2 1
1 3
2 3
1 4
1 5
5 4
C 1 50
A 3 1
C 3 60
A 4 1
A 4 3
A 3 4
*/
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
#define REP(i,j,k)     for(int i = j ; i < k ; ++i)
#define RREP(i,j,k)    for(int i = j ; i >=k ; --i)
#define A    first
#define B    second
#define mp   make_pair
#define pb   emplace_back
#define PII pair<int , int>
#define MEM(i,j)   memset(i , j , sizeof i)
#define ALL(i)     i.begin() , i.end()
#define DBGG(i,j)     cout << i << " " << j << endl
#define DB4(i,j,k,l)  cout << i << " " << j << " " << k << " " << l << endl
#define IOS cin.tie() , cout.sync_with_stdio(0)
// #define endl "\n"
///------------------------------------------------------------
#define MAX 300900
#define INF 0x3f3f3f3f
#define mid ((l + r) >> 1)
#define ls (now << 1)
#define rs (now << 1 | 1)

int n , m , k , x[MAX];
int cut[MAX] , bcc[MAX] , bccpo;
struct Decomposition{
	vector<int> v[MAX];
	multiset<int> dotval[MAX];
	int sml[MAX * 4];
	int pat[MAX] , son[MAX] , siz[MAX] , dep[MAX];
	int top[MAX] , id[MAX] , idpo = 0;
	void DFS1(int now , int fa , int deep){
		pat[now] = fa;
		dep[now] = deep;
		son[now] = 0;
		siz[now] = 1;
		for(auto to : v[now]){
			if(to == fa) continue;
			DFS1(to , now , deep + 1);
			siz[now] += siz[to];
			if(siz[to] > siz[son[now]]) son[now] = to;
		}
	}
	void DFS2(int now , int fa , int root){
		id[now] = ++idpo;
		// DB4("id[" , now , "] = " , idpo);
		top[now] = root;
		if(son[now]) DFS2(son[now] , now , root);
		for(auto to : v[now]){
			if(to == fa || to == son[now]) continue;
			DFS2(to , now , to);
		}
	}
	void update(int now , int l , int r , int k , int v){
		// if(now == 1) DB4("update = " , k , v , "");
		if(l == k && r == k) sml[now] = v;
		else {
			if(k <= mid + 0) update(ls , l , mid + 0 , k , v);
			if(mid + 1 <= k) update(rs , mid + 1 , r , k , v);
			sml[now] = min(sml[ls] , sml[rs]);
		}
	}
	int query(int now , int l , int r , int ql , int qr){
		if(ql > qr) swap(ql , qr);
		if(ql <= l && r <= qr) return sml[now];
		else if(qr <= mid + 0) return query(ls , l , mid + 0 , ql , qr);
		else if(mid + 1 <= ql) return query(rs , mid + 1 , r , ql , qr);
		return min(query(ls , l , mid + 0 , ql , qr) , query(rs , mid + 1 , r , ql , qr));
	}
	int update(int dot , int from , int val){
		dotval[dot].erase(dotval[dot].find(from));
		dotval[dot].insert(val);
		update(1 , 1 , idpo , id[dot] , *dotval[dot].begin());
	}
	int query(int a , int b){
		// cout << "in" << endl;
		int t1 = top[a] , t2 = top[b] , ans = INF;
		while(t1 != t2){
			// DB4(a , t1 , b , t2);
			// if(a == 0 && t1 == 0) break;
			if(dep[t1] < dep[t2]) swap(a , b) , swap(t1 , t2);
			ans = min(ans , query(1 , 1 , idpo , id[a] , id[t1]));
			a = pat[t1] , t1 = top[a];
		}
		int tmp = (id[a] < id[b]) ? a : b;
		if(tmp > n) ans = min(ans , x[pat[tmp]]);
		ans = min(ans , query(1 , 1 , idpo , id[a] , id[b]));
		return ans;
	}
	int print(int now , int l , int r){
		if(l == r) cout << sml[now] << " ";
		else print(ls , l , mid + 0) , print(rs , mid + 1 , r);
	}
	int solveinit(){
		v[0].pb(1);
		DFS1(0 , 0 , 0);
		DFS2(0 , 0 , 0);
		MEM(sml , INF);
		REP(i , 1 , n + 1){
			dotval[i].insert(x[i]);
			dotval[pat[i]].insert(x[i]);
		}
		// REP(i , 1 , bccpo){
		// 	cout << "now i " << i << " = ";
		// 	for(auto to : dotval[i]){
		// 		cout << to << " ";
		// 	} cout << endl;
		// }
		REP(i , 1 , bccpo){
			update(1 , 1 , idpo , id[i] , *dotval[i].begin());
		}
	}
} solver;
struct Tarjan{
	vector<int> v[MAX];
	set<int> cc[MAX];

	int low[MAX] , dep[MAX] , use[MAX];
	stack<PII> sk;
	void DFS(int now , int fa , int deep){
		cut[now] = 0;
		use[now] = 1;
		low[now] = deep;
		dep[now] = deep;
		int son = 0;
		for(auto to : v[now]){
			if(use[to]) low[now] = min(low[now] , dep[to]);
			else {
				sk.push(mp(now , to));
				son ++ , DFS(to , now , deep + 1);
				low[now] = min(low[now] , low[to]);
				if(low[to] >= dep[now]){
					cut[now] = 1;
					while(sk.size()){
						int a = sk.top().A , b = sk.top().B;
						sk.pop();
						cc[bccpo].insert(a);
						bcc[a] = bccpo;
						bcc[b] = bccpo;
						cc[bccpo].insert(b);
						if(now == a && to == b) break;
						if(now == b && to == a) break;
					}
					bccpo ++;
				}
			}
		}
		if(deep == 0) cut[now] = (son >= 2);
	}
	void Build(){
		REP(i , n + 1 , bccpo){
			for(auto to : cc[i]){
				solver.v[i].pb(to);
				solver.v[to].pb(i);
				// DBGG(i , to);
			}
		}
	}
	void solveinit(){
		MEM(use , 0);
		bccpo = n + 1;
		DFS(1 , 0 , 0);
		Build();
	}
} cuter;
int32_t main(){
	IOS , cin >> n >> m >> k;
	REP(i , 1 , n + 1){
		cin >> x[i];
	}
	REP(i , 1 , m + 1){
		int a , b; cin >> a >> b;
		cuter.v[a].pb(b) , cuter.v[b].pb(a);
	}

	cuter.solveinit();
	solver.solveinit();

	// REP(i , 1 , n + 1) if(cut[i]) DBGG("find one = " , i);

	char ty;
	int a , b;
	REP(i , 1 , k + 1){
		cin >> ty >> a >> b;
		if(ty == 'A') cout << solver.query(a , b) << endl;
		if(ty == 'C'){
			solver.update(a , x[a] , b);
			solver.update(solver.pat[a] , x[a] , b);
			x[a] = b;
		}
		// cout << "result = "; solver.print(1 , 1 , solver.idpo); cout << endl;
	}
    return 0;
}


#include<bits/stdc++.h>

#define LL long long
#define RG register

using namespace std;
template<class T> T gi() {
	T x = 0; bool f = 0; char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = 1, c = getchar();
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return f ? -x : x;
}
const int N = 2e5 + 10;
struct node { int to, nxt; } g[N << 1];
int lst[N], gl, cnt, w[N], dfn[N], low[N], fa[N], son[N], top[N], pos[N], tim;
int dep[N], siz[N], n, m, q;
void add(int x, int y) {
	g[++gl] = (node) {y, lst[x]}; lst[x] = gl;
	g[++gl] = (node) {x, lst[y]}; lst[y] = gl;
}
vector<int> e[N];
multiset<int> S[N];
stack<int> stk;
void tarjan(int u) {
	stk.push(u); dfn[u] = low[u] = ++tim;
	for (int i = lst[u]; i; i = g[i].nxt) {
		int v = g[i].to;
		if (!dfn[v]) {
			tarjan(v); low[u] = min(low[u], low[v]);
			if (low[v] == dfn[u]) {
				cnt++;
				for (int x = 0; x != v;) {
					x = stk.top(); stk.pop();
					e[x].push_back(cnt);
					e[cnt].push_back(x);
				}
				e[cnt].push_back(u);
				e[u].push_back(cnt);
			}
		}
		else low[u] = min(low[u], dfn[v]);
	}
}
void dfs1(int u, int ff) {
	fa[u] = ff; siz[u] = 1;
	for (auto v : e[u])
		if (v != ff) {
			dep[v] = dep[u] + 1; dfs1(v, u);
			siz[u] += siz[v];
			if (siz[son[u]] < siz[v]) son[u] = v;
		}
}
void dfs2(int u, int tf) {
	top[u] = tf; dfn[pos[u] = ++tim] = u;
	if (!son[u]) return ;
	dfs2(son[u], tf);
	for (auto v : e[u])
		if (v != fa[u] && v != son[u])
			dfs2(v, v);
}
#define lson (o << 1)
#define rson (o << 1 | 1)
int t[N << 2];
void pushup(int o) { t[o] = min(t[lson], t[rson]); }
void build(int o, int l, int r) {
	if (l == r) return (void) (t[o] = w[dfn[l]]);
	int mid = (l + r) >> 1;
	build(lson, l, mid), build(rson, mid + 1, r);
	pushup(o);
}
void Modify(int o, int l, int r, int p, int k) {
	if (l == r) return (void) (t[o] = k);
	int mid = (l + r) >> 1;
	if (p <= mid) Modify(lson, l, mid, p, k);
	else Modify(rson, mid + 1, r, p, k);
	pushup(o);
}
int query(int o, int l, int r, int L, int R) {
	if (L <= l && r <= R) return t[o];
	int mid = (l + r) >> 1, res = 2147483647;
	if (L <= mid) res = query(lson, l, mid, L, R);
	if (R > mid) res = min(res, query(rson, mid + 1, r, L, R));
	return res;
}
int query(int x, int y) {
	int res = 2147483647;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		res = min(res, query(1, 1, cnt, pos[top[x]], pos[x]));
		x = fa[top[x]];
	}
	if (dep[x] > dep[y]) swap(x, y);
	if (x > n) res = min(res, w[fa[x]]);
	return min(res, query(1, 1, cnt, pos[x], pos[y]));
}
int main() {
	//freopen(".in", "r", stdin);
	//freopen(".out", "w", stdout);
	cnt = n = gi<int>(), m = gi<int>(), q = gi<int>();
	for (int i = 1; i <= n; i++) w[i] = gi<int>();
	for (int i = 1; i <= m; i++) add(gi<int>(), gi<int>());
	tarjan(1); tim = 0; dfs1(1, 0); dfs2(1, 1);
	for (int i = n + 1; i <= cnt; i++) {
		for (auto v : e[i])
			if (v != fa[i])
				S[i].insert(w[v]);
		w[i] = *S[i].begin();
	}
	build(1, 1, cnt);
	while (q--) {
		char c = getchar(); int a = gi<int>(), b = gi<int>();
		if (c == 'A') printf("%d\n", query(a, b));
		else {
			if (fa[a])
				S[fa[a]].erase(S[fa[a]].find(w[a]));
			w[a] = b; Modify(1, 1, cnt, pos[a], b);
			if (fa[a])
				S[fa[a]].insert(w[a]), w[fa[a]] = *S[fa[a]].begin(), Modify(1, 1, cnt, pos[fa[a]], w[fa[a]]);
		}
	}
	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[M], idxer, bcc, tp;
bool mark[N]; int stk2[N], tp2;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
int pw[N << 1];
std::multiset<int> st[N << 1];

int n, m, q;

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			stk[++tp] = i;
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				tp2 = 0;
				do
				{
					int t = G[stk[tp]];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
					t = G[stk[tp] ^ 1];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
				}
				while(stk[tp--] != i);
				while(tp2) mark[stk2[tp2]] = 0, tp2--;
			}
		}
		else if(dfn[v] < dfn[u])
		{
			stk[++tp] = i;
			chk_min(low[u], dfn[v]);
		}
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
				ST.update(1, lfn[fa[a]], pw[fa[a]], 1, n + bcc);
			}
			pw[a] = b;
			ST.update(1, lfn[a], b, 1, n + bcc);

		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[N], idxer, bcc, tp;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
int pw[N << 1];
std::multiset<int> st[N << 1];

int n, m, q;

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	stk[++tp] = u;

	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				do
				{
					T.add(n + bcc, stk[tp]);
					T.add(stk[tp], n + bcc);
				}
				while(stk[tp--] != v);
				T.add(n + bcc, u), T.add(u, n + bcc);
			}
		}
		else if(dfn[v] < dfn[u])
			chk_min(low[u], dfn[v]);
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
				ST.update(1, lfn[fa[a]], pw[fa[a]], 1, n + bcc);
			}
			pw[a] = b;
			ST.update(1, lfn[a], b, 1, n + bcc);

		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[N], idxer, bcc, tp;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
int pw[N << 1];
std::multiset<int> st[N << 1];

int n, m, q;

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	stk[++tp] = u;

	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				do
				{
					T.add(n + bcc, stk[tp]);
					T.add(stk[tp], n + bcc);
				}
				while(stk[tp--] != u);
				stk[++tp] = u;
			}
		}
		else if(dfn[v] < dfn[u])
			chk_min(low[u], dfn[v]);
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
				ST.update(1, lfn[fa[a]], pw[fa[a]], 1, n + bcc);
			}
			pw[a] = b;
			ST.update(1, lfn[a], b, 1, n + bcc);

		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[M], idxer, bcc, tp;
bool mark[N]; int stk2[N], tp2;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
std::multiset<int> st[N << 1];

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

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			stk[++tp] = i;
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				tp2 = 0;
				do
				{
					int t = G[stk[tp]];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
				}
				while(stk[tp--] != i);
				while(tp2) mark[stk2[tp2]] = 0, tp2--;
			}
		}
		else if(dfn[v] < dfn[u])
		{
			stk[++tp] = i;
			chk_min(low[u], dfn[v]);
		}
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			ST.update(1, lfn[a], b, 1, n + bcc);
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
			}
			pw[a] = b;
		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[N], idxer, bcc, tp;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
int pw[N << 1];
std::multiset<int> st[N << 1];

int n, m, q;

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	stk[++tp] = u;

	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				do
				{
					T.add(n + bcc, stk[tp]);
					T.add(stk[tp], n + bcc);
				}
				while(stk[tp--] != v);
				T.add(n + bcc, v), T.add(v, n + bcc);
			}
		}
		else if(dfn[v] < dfn[u])
			chk_min(low[u], dfn[v]);
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
				ST.update(1, lfn[fa[a]], pw[fa[a]], 1, n + bcc);
			}
			pw[a] = b;
			ST.update(1, lfn[a], b, 1, n + bcc);

		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
    int head[N], nxt[M], tot; T to[M];
    Linked_List() {clear();}
    T &operator [](const int x) {return to[x];}
    void clear() {memset(head, -1, sizeof(head)), tot = 0;}
    void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
    #define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[M], bel[M], idxer, bcc, tp;
bool mark[N]; int stk2[N], tp2;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
std::multiset<int> st[N << 1];

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

void tarjan(int u, int fa_e)
{
    dfn[u] = low[u] = ++idxer;
    EOR(i, G, u)
    {
        if(i == (fa_e ^ 1)) continue;
        int v = G[i];
        if(!dfn[v])
        {
            stk[++tp] = i / 2;
            tarjan(v, i), chk_min(low[u], low[v]);
            if(low[v] >= dfn[u])
            {
                bcc++;
				tp2 = 0;
                do
				{
					int t = G[stk[tp]];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
					bel[stk[tp]] = bcc;
				}
                while(stk[tp--] != i / 2);
				while(tp2) mark[stk2[tp2]] = 0, tp2--;
            }
        }
        else if(dfn[v] < dfn[u])
        {
            stk[++tp] = i / 2;
            chk_min(low[u], dfn[v]);
        }
    }
}

void dfs(int u, int f, int d)
{
    fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
    EOR(i, T, u)
    {
        int v = T[i];
        if(v == f) continue;
        dfs(v, u, d + 1);
        sz[u] += sz[v];
        if(sz[v] > sz[son[u]]) son[u] = v;
    }
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
    top[u] = tp;
    if(son[u]) hld(son[u], tp);
    EOR(i, T, u)
    {
        int v = T[i];
        if(v == fa[u] || v == son[u]) continue;
        hld(v, v);
    }
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
    while(top[u] != top[v])
    {
        if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
        u = fa[top[u]];
    }
    return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			ST.update(1, lfn[a], b, 1, n + bcc);
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
			}
			pw[a] = b;
		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

    return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[M], idxer, bcc, tp;
bool mark[N]; int stk2[N], tp2;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
std::multiset<int> st[N << 1];

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

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			stk[++tp] = i;
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				tp2 = 0;
				do
				{
					int t = G[stk[tp]];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
					t = G[stk[tp] ^ 1];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
				}
				while(stk[tp--] != i);
				while(tp2) mark[stk2[tp2]] = 0, tp2--;
			}
		}
		else if(dfn[v] < dfn[u])
		{
			stk[++tp] = i;
			chk_min(low[u], dfn[v]);
		}
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
				ST.update(1, lfn[fa[a]], pw[fa[a]], 1, n + bcc);
			}
			pw[a] = b;
			ST.update(1, lfn[a], b, 1, n + bcc);

		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include<bits/stdc++.h>
#define FOR(i, x, y) for(int i = (x), i##END = (y); i <= i##END; ++i)
#define DOR(i, x, y) for(int i = (x), i##END = (y); i >= i##END; --i)
template<typename T, typename _T> inline bool chk_min(T &x, const _T &y) {return y < x ? x = y, 1 : 0;}
template<typename T, typename _T> inline bool chk_max(T &x, const _T &y) {return x < y ? x = y, 1 : 0;}
typedef long long ll;
const int N = 100005;
const int M = 100005;

template<const int N, const int M, typename T> struct Linked_List
{
	int head[N], nxt[M], tot; T to[M];
	Linked_List() {clear();}
	T &operator [](const int x) {return to[x];}
	void clear() {memset(head, -1, sizeof(head)), tot = 0;}
	void add(int u, T v) {to[tot] = v, nxt[tot] = head[u], head[u] = tot++;}
	#define EOR(i, G, u) for(int i = G.head[u]; ~i; i = G.nxt[i])
};

struct Segment_Tree
{
	int mi[N << 3];
	void update(int k, int x, int val, int l, int r)
	{
		if(l == r) {mi[k] = val; return;}
		int mid = (l + r) >> 1;
		if(x <= mid) update(k << 1, x, val, l, mid);
		else update(k << 1 | 1, x, val, mid + 1, r);
		mi[k] = std::min(mi[k << 1], mi[k << 1 | 1]);
	}
	int query(int k, int L, int R, int l, int r)
	{
		if(L <= l && r <= R) return mi[k];
		int mid = (l + r) >> 1;
		if(R <= mid) return query(k << 1, L, R, l, mid);
		else if(L > mid) return query(k << 1 | 1, L, R, mid + 1, r);
		else return std::min(query(k << 1, L, R, l, mid), query(k << 1 | 1, L, R, mid + 1, r));
	}
};

Linked_List<N, M << 1, int> G;
Linked_List<N << 1, N << 2, int> T;
Segment_Tree ST;

int dfn[N], low[N], stk[M], idxer, bcc, tp;
bool mark[N]; int stk2[N], tp2;

int fa[N << 1], dep[N << 1], sz[N << 1], son[N << 1], top[N << 1];
int lfn[N << 1], rfn[N << 1], ori[N << 1], dfn_idx;
std::multiset<int> st[N << 1];

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

void tarjan(int u, int fa_e)
{
	dfn[u] = low[u] = ++idxer;
	EOR(i, G, u)
	{
		if(i == (fa_e ^ 1)) continue;
		int v = G[i];
		if(!dfn[v])
		{
			stk[++tp] = i;
			tarjan(v, i), chk_min(low[u], low[v]);
			if(low[v] >= dfn[u])
			{
				bcc++;
				tp2 = 0;
				do
				{
					int t = G[stk[tp]];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}
					t = G[stk[tp] ^ 1];
					if(!mark[t])
					{
						stk2[++tp2] = t;
						mark[t] = 1;
						T.add(n + bcc, t);
						T.add(t, n + bcc);
					}

				}
				while(stk[tp--] != i);
				while(tp2) mark[stk2[tp2]] = 0, tp2--;
			}
		}
		else if(dfn[v] < dfn[u])
		{
			stk[++tp] = i;
			chk_min(low[u], dfn[v]);
		}
	}
}

void dfs(int u, int f, int d)
{
	fa[u] = f, dep[u] = d, sz[u] = 1, son[u] = 0;
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == f) continue;
		dfs(v, u, d + 1);
		sz[u] += sz[v];
		if(sz[v] > sz[son[u]]) son[u] = v;
	}
}

void hld(int u, int tp)
{
	ori[lfn[u] = ++dfn_idx] = u;
	top[u] = tp;
	if(son[u]) hld(son[u], tp);
	EOR(i, T, u)
	{
		int v = T[i];
		if(v == fa[u] || v == son[u]) continue;
		hld(v, v);
	}
	rfn[u] = dfn_idx;
}

int get_lca(int u, int v)
{
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		u = fa[top[u]];
	}
	return dep[u] < dep[v] ? u : v;
}

int query(int u, int v)
{
	int res = 2e9;
	while(top[u] != top[v])
	{
		if(dep[top[u]] < dep[top[v]]) std::swap(u, v);
		chk_min(res, ST.query(1, lfn[top[u]], lfn[u], 1, n + bcc));
		u = fa[top[u]];
	}
	if(dep[u] > dep[v]) std::swap(u, v);
	chk_min(res, ST.query(1, lfn[u], lfn[v], 1, n + bcc));
	if(u > n) chk_min(res, pw[fa[u]]);
	return res;
}

int main()
{
	scanf("%d%d%d", &n, &m, &q);
	FOR(i, 1, n) scanf("%d", &pw[i]);
	FOR(i, 1, m)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		G.add(u, v), G.add(v, u);
	}

	tarjan(1, -1);
	dfs(1, 0, 1), hld(1, 1);

	FOR(u, n + 1, n + bcc)
	{
		EOR(i, T, u)
		{
			int v = T[i];
			if(v == fa[u]) continue;
			st[u].insert(pw[v]);
		}
		pw[u] = (*st[u].begin());
	}

	FOR(i, 1, n + bcc) ST.update(1, lfn[i], pw[i], 1, n + bcc);

	while(q--)
	{
		char str[3]; int a, b;
		scanf("%s%d%d", str, &a, &b);
		if(str[0] == 'C')
		{
			ST.update(1, lfn[a], b, 1, n + bcc);
			if(fa[a])
			{
				st[fa[a]].erase(st[fa[a]].find(pw[a]));
				st[fa[a]].insert(b);
				pw[fa[a]] = (*st[fa[a]].begin());
			}
			pw[a] = b;
		}
		else if(str[0] == 'A')
			printf("%d\n", query(a, b));
	}

	return 0;
}


#include <bits/stdc++.h>

#define pii pair<int, int>
#define x first
#define y second

using namespace std;

const int N = 2e5 + 5;

struct Heap {
    priority_queue<int, vector<int>, greater<int> > P, Q;
    void add(int x) { P.emplace(x); }
    void del(int x) { Q.emplace(x); }
    void adjust() {
        while(!Q.empty() && P.top() == Q.top())
            P.pop(), Q.pop();
    }
    int top() { adjust(); return P.top(); }
} Q[N];

struct SegmentTree {
    int t[N << 1];
    void update(int x, int k) {
        for(t[x += N] = k; x != 1; x >>= 1)
            t[x >> 1] = min(t[x], t[x ^ 1]);
    }
    int query(int l, int r) {
        int ret = 2e9;
        for(l += N, r += N + 1; l < r; l >>= 1, r >>= 1) {
            if(l & 1) ret = min(ret, t[l++]);
            if(r & 1) ret = min(ret, t[--r]);
        }
        return ret;
    }
} tree;

int n, sz, m, q, w[N];
vector<vector<int> > g(N), bcc;

int low[N], pre[N], art[N], id[N];
bitset<N> idart;

void tarjan(int u, int p) {
    static int idx = 0;
    static stack<int> S;

    pre[u] = low[u] = ++idx;
    S.emplace(u);
    int child = 0;
    for(int v : g[u]) if(v != p) {
        if(!pre[v]) {
            ++child;
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if((!p && child > 1) || (p && low[v] >= pre[u]))
                art[u] = true;
            if(low[v] >= pre[u]) {
                bcc.emplace_back(1, u);
                while(bcc.back().back() != v) {
                    bcc.back().emplace_back(S.top());
                    S.pop();
                }
            }
        } else low[u] = min(low[u], pre[v]);
    }
}

int par[N], dep[N], spi[N], rot[N], pos[N];

int dfs(int u, int p) {
    par[u] = p, dep[u] = dep[p] + 1;
    int sz = 1; pii ret(0, -1);
    for(int v : g[u]) if(v != p) {
        int z = dfs(v, u);
        sz += z, ret = max(ret, pii(z, v));
    }
    spi[u] = ret.y;
    return sz;
}

void gen_bct() {
    tarjan(1, 0);
    g.clear(), g.emplace_back(0);
    for(int i = 1; i <= n; i++) if(art[i]) {
        g.emplace_back(0);
        idart[id[i] = g.size() - 1] = true;
        Q[id[i]].add(w[i]);
    }
    for(vector<int> &cc : bcc) {
        g.emplace_back(0);
        for(int u : cc) {
            if(art[u]) g[g.size() - 1].emplace_back(id[u]), g[id[u]].emplace_back(g.size() - 1);
            else id[u] = g.size() - 1, Q[g.size() - 1].add(w[u]);
        }
    }
    sz = g.size() - 1;
    dfs(1, 0);
    for(int i = 1; i <= n; i++) if(art[i]) Q[par[id[i]]].add(w[i]);
    for(int i = 1, idx = 0; i <= sz; i++) if(spi[par[i]] != i)
        for(int j = i; j != -1; j = spi[j])
            rot[j] = i, pos[j] = ++idx;
    for(int i = 1; i <= sz; i++) tree.update(pos[i], Q[i].top());
}

pii hld_query(int a, int b) {
    int ans = 2e9;
    while(rot[a] != rot[b]) {
        if(dep[rot[a]] < dep[rot[b]]) swap(a, b);
        ans = min(ans, tree.query(pos[rot[a]], pos[a]));
        a = par[rot[a]];
    }
    if(dep[a] < dep[b]) swap(a, b);
    ans = min(ans, tree.query(pos[b], pos[a]));
    return pii(ans, b);
}

int main() {
    scanf("%d %d %d", &n, &m, &q);
    for(int i = 1; i <= n; i++) scanf("%d", w + i);
    for(int i = 1, a, b; i <= m; i++) {
        scanf("%d %d", &a, &b);
        g[a].emplace_back(b);
        g[b].emplace_back(a);
    }
    gen_bct();

    for(int i = 1; i <= q; i++) {
        char T; int a, b;
        scanf(" %c %d %d", &T, &a, &b);
        if(T == 'A') {
            if(a == b) printf("%d\n", w[a]);
            else {
                a = id[a], b = id[b];
                if(a == b) {
                    int now = tree.query(pos[a], pos[a]);
                    if(!idart[a] && par[a]) now = min(now, Q[par[a]].top());
                    printf("%d\n", now);
                } else {
                    pii now = hld_query(a, b);
                    if(!idart[now.y] && par[now.y])
                        now.x = min(now.x, Q[par[now.y]].top());
                    printf("%d\n", now.x);
                }
            }
        } else {
            int pre = w[a];
            w[a] = b, a = id[a];
            Q[a].del(pre), Q[a].add(b);
            tree.update(pos[a], Q[a].top());
            if(idart[a] && par[a]) {
                Q[par[a]].del(pre), Q[par[a]].add(b);
                tree.update(pos[par[a]], Q[par[a]].top());
            }
        }
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int cnt1,nex1[500005],las1[500005],Arrive1[500005],cnt2,nex2[500005],las2[500005],Arrive2[500005];
int N,M,Q,Bcc_cnt;
int w[500005];
multiset<int> S[500005];
int dfn[500005],Low[500005],Timew;
int stk[500005],tp;
void jt1(int x,int y){
	cnt1++;
	nex1[cnt1]=las1[x];
	las1[x]=cnt1;
	Arrive1[cnt1]=y;
}
void jt2(int x,int y){
	cnt2++;
	nex2[cnt2]=las2[x];
	las2[x]=cnt2;
	Arrive2[cnt2]=y;
}
void Tarjan(int Now){
	//cout<<Now<<endl;
	Low[Now]=dfn[Now]=++Timew;
	stk[++tp]=Now;
	for (int i=las1[Now];i;i=nex1[i]){
		if (!dfn[Arrive1[i]]){
			Tarjan(Arrive1[i]);
			Low[Now]=min(Low[Now],Low[Arrive1[i]]);
			if (Low[Arrive1[i]]==dfn[Now]){
				++Bcc_cnt;
				for (int x=0;x!=Arrive1[i];--tp){
					x=stk[tp];
					jt2(Bcc_cnt,x);
					jt2(x,Bcc_cnt);
				}
				jt2(Bcc_cnt,Now);
				jt2(Now,Bcc_cnt);
			}
		}
		else Low[Now]=min(Low[Now],dfn[Arrive1[i]]);
	}
}
int idf[500005],fa[500005],Siz[500005],dep[500005],Son[500005],top[500005],dfc;
void dfs1(int Now,int Fa){
	fa[Now]=Fa;dep[Now]=dep[Fa]+1;Siz[Now]=1;
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa){
			dfs1(Arrive2[i],Now);
			Siz[Now]+=Siz[Arrive2[i]];
			if (Siz[Son[Now]]<Siz[Arrive2[i]]) Son[Now]=Arrive2[i];
		}
}
void dfs2(int Now,int Fa,int tp){
	dfn[Now]=++dfc,idf[dfc]=Now,top[Now]=tp;
	if (Son[Now]) dfs2(Son[Now],Now,tp);
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa&&Arrive2[i]!=Son[Now])
			dfs2(Arrive2[i],Now,Arrive2[i]);
}
int Tree[500005];
void Build(int Now,int l,int r){
	if (l==r) {Tree[Now]=w[idf[l]]; return;}
	int mid=(l+r)>>1;
	Build(Now<<1,l,mid),Build(Now<<1|1,mid+1,r);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
void Modify(int Now,int l,int r,int Pos,int x){
	if (l==r) {Tree[Now]=x;return;}
	int mid=(l+r)>>1;
	if (Pos<=mid) Modify(Now<<1,l,mid,Pos,x);
	else Modify(Now<<1|1,mid+1,r,Pos,x);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
int query(int Now,int l,int r,int L,int R){
	if (r<L||l>R) return 1e9+7;
	if (L<=l&&r<=R) return Tree[Now];
	int mid=(l+r)>>1;
	return min(query(Now<<1,l,mid,L,R),query(Now<<1|1,mid+1,r,L,R));
}
int main(){
	scanf("%d%d",&N,&M);
	scanf("%d",&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&w[i]);
	Bcc_cnt=N;
	for (int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		jt1(u,v);
		jt1(v,u);
	}
	Tarjan(1),dfs1(1,0),dfc=0,dfs2(1,0,1);
	for (int i=1;i<=N;i++)
		if (fa[i]) S[fa[i]].insert(w[i]);
	for (int i=N+1;i<=Bcc_cnt;i++)
		w[i]=*S[i].begin();
	Build(1,1,Bcc_cnt);
	while (Q--){
		char opt[3];int x,y;
		scanf("%s%d%d",opt,&x,&y);
		if (*opt=='C'){
			Modify(1,1,Bcc_cnt,dfn[x],y);
			if (fa[x]){
				int u=fa[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();
					Modify(1,1,Bcc_cnt,dfn[u],w[u]);
				}
			}
			w[x]=y;
		}
		else{
			int Ans=1e9+7;
			while (top[x]!=top[y]){
				if (dep[top[x]]<dep[top[y]]) swap(x,y);
			Ans=min(Ans,query(1,1,Bcc_cnt,dfn[top[x]],dfn[x]));
			x=fa[top[x]];
		  }
		  if (dfn[x]>dfn[y]) swap(x,y);
		  Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
		  if (x>N)
		  Ans=min(Ans,w[fa[x]]);
		  printf("%d\n",Ans);
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
int cnt1,nex1[100005],las1[1000005],Arrive1[1000005],cnt2,nex2[100005],las2[10005],Arrive2[100005];
int N,M,Q,Bcc_cnt;
int w[200005];
multiset<int> S[200005];
int dfn[200005],Low[200005],Timew;
int stk[200005],tp;
void jt1(int x,int y){
	cnt1++;
	nex1[cnt1]=las1[x];
	las1[x]=cnt1;
	Arrive1[cnt1]=y;
}
void jt2(int x,int y){
	cnt2++;
	nex2[cnt2]=las2[x];
	las2[x]=cnt2;
	Arrive2[cnt2]=y;
}
void Tarjan(int Now){
	//cout<<Now<<endl;
	Low[Now]=dfn[Now]=++Timew;
	stk[++tp]=Now;
	for (int i=las1[Now];i;i=nex1[i]){
		if (!dfn[Arrive1[i]]){
			Tarjan(Arrive1[i]);
			Low[Now]=min(Low[Now],Low[Arrive1[i]]);
			if (Low[Arrive1[i]]==dfn[Now]){
				++Bcc_cnt;
				for (int x=0;x!=Arrive1[i];--tp){
					x=stk[tp];
					jt2(Bcc_cnt,x);
					jt2(x,Bcc_cnt);
				}
				jt2(Bcc_cnt,Now);
				jt2(Now,Bcc_cnt);
			}
		}
		else Low[Now]=min(Low[Now],dfn[Arrive1[i]]);
	}
}
int idf[100005],fa[1000005],Siz[1000005],dep[100005],Son[100005],top[100005],dfc;
void dfs1(int Now,int Fa){
	fa[Now]=Fa;dep[Now]=dep[Fa]+1;Siz[Now]=1;
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa){
			dfs1(Arrive2[i],Now);
			Siz[Now]+=Siz[Arrive2[i]];
			if (Siz[Son[Now]]<Siz[Arrive2[i]]) Son[Now]=Arrive2[i];
		}
}
void dfs2(int Now,int Fa,int tp){
	dfn[Now]=++dfc,idf[dfc]=Now,top[Now]=tp;
	if (Son[Now]) dfs2(Son[Now],Now,tp);
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa&&Arrive2[i]!=Son[Now])
			dfs2(Arrive2[i],Now,Arrive2[i]);
}
int Tree[1000005];
void Build(int Now,int l,int r){
	if (l==r) {Tree[Now]=w[idf[l]]; return;}
	int mid=(l+r)>>1;
	Build(Now<<1,l,mid),Build(Now<<1|1,mid+1,r);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
void Modify(int Now,int l,int r,int Pos,int x){
	if (l==r) {Tree[Now]=x;return;}
	int mid=(l+r)>>1;
	if (Pos<=mid) Modify(Now<<1,l,mid,Pos,x);
	else Modify(Now<<1|1,mid+1,r,Pos,x);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
int query(int Now,int l,int r,int L,int R){
	if (r<L||l>R) return 1e9+7;
	if (L<=l&&r<=R) return Tree[Now];
	int mid=(l+r)>>1;
	return min(query(Now<<1,l,mid,L,R),query(Now<<1|1,mid+1,r,L,R));
}
int main(){
	scanf("%d%d",&N,&M);
	scanf("%d",&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&w[i]);
	Bcc_cnt=N;
	for (int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		jt1(u,v);
		jt1(v,u);
	}
	Tarjan(1),dfs1(1,0),dfc=0,dfs2(1,0,1);
	for (int i=1;i<=N;i++)
		if (fa[i]) S[fa[i]].insert(w[i]);
	for (int i=N+1;i<=Bcc_cnt;i++)
		w[i]=*S[i].begin();
	Build(1,1,Bcc_cnt);
	while (Q--){
		char opt[3];int x,y;
		scanf("%s%d%d",opt,&x,&y);
		if (*opt=='C'){
			Modify(1,1,Bcc_cnt,dfn[x],y);
			if (fa[x]){
				int u=fa[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();
					Modify(1,1,Bcc_cnt,dfn[u],w[u]);
				}
			}
			w[x]=y;
		}
		else{
			int Ans=1e9+7;
			while (top[x]!=top[y]){
				if (dep[top[x]]<dep[top[y]]) swap(x,y);
			Ans=min(Ans,query(1,1,Bcc_cnt,dfn[top[x]],dfn[x]));
			x=fa[top[x]];
		  }
		  if (dfn[x]>dfn[y]) swap(x,y);
		  Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
		  if (x>N)
		  Ans=min(Ans,w[fa[x]]);
		  printf("%d\n",Ans);
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
int cnt1,nex1[100005],las1[1000005],Arrive1[1000005],cnt2,nex2[100005],las2[10005],Arrive2[100005];
int N,M,Q,Bcc_cnt;
int w[200005];
multiset<int> S[200005];
int dfn[200005],Low[200005],Timew;
int stk[200005],tp;
void jt1(int x,int y){
	cnt1++;
	nex1[cnt1]=las1[x];
	las1[x]=cnt1;
	Arrive1[cnt1]=y;
}
void jt2(int x,int y){
	cnt2++;
	nex2[cnt2]=las2[x];
	las2[x]=cnt2;
	Arrive2[cnt2]=y;
}
void Tarjan(int Now){
	Low[Now]=dfn[Now]=++Timew;
	stk[++tp]=Now;
	for (int i=las1[Now];i;i=nex1[i]){
		if (!dfn[Arrive1[i]]){
			Tarjan(Arrive1[i]);
			Low[Now]=min(Low[Now],Low[Arrive1[i]]);
			if (Low[Now]==dfn[Now]){
				++Bcc_cnt;
				for (int x=0;x!=Arrive1[i];--tp){
					x=stk[tp];
					jt2(Bcc_cnt,x);
					jt2(x,Bcc_cnt);
				}
				jt2(Bcc_cnt,Now);
				jt2(Now,Bcc_cnt);
			}
		}
		else Low[Now]=min(Low[Now],dfn[Arrive1[i]]);
	}
}
int idf[100005],fa[1000005],Siz[1000005],dep[100005],Son[100005],top[100005],dfc;
void dfs1(int Now,int Fa){
	fa[Now]=Fa;dep[Now]=dep[Fa]+1;Siz[Now]=1;
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa){
			dfs1(Arrive2[i],Now);
			Siz[Now]+=Siz[Arrive2[i]];
			if (Siz[Son[Now]]<Siz[Arrive2[i]]) Son[Now]=Arrive2[i];
		}
}
void dfs2(int Now,int Fa,int tp){
	dfn[Now]=++dfc,idf[dfc]=Now,top[Now]=tp;
	if (Son[Now]) dfs2(Son[Now],Now,tp);
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa&&Arrive2[i]!=Son[Now])
			dfs2(Arrive2[i],Now,Arrive2[i]);
}
int Tree[1000005];
void Build(int Now,int l,int r){
	if (l==r) {Tree[Now]=w[idf[l]]; return;}
	int mid=(l+r)>>1;
	Build(Now<<1,l,mid),Build(Now<<1|1,mid+1,r);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
void Modify(int Now,int l,int r,int Pos,int x){
	if (l==r) {Tree[Now]=x;return;}
	int mid=(l+r)>>1;
	if (Pos<=mid) Modify(Now<<1,l,mid,Pos,x);
	else Modify(Now<<1|1,mid+1,r,Pos,x);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
int query(int Now,int l,int r,int L,int R){
	if (r<L||l>R) return 1e9;
	if (L<=l&&r<=R) return Tree[Now];
	int mid=(l+r)>>1;
	return min(query(Now<<1,l,mid,L,r),query(Now<<1|1,mid+1,r,L,R));
}
int main(){
	scanf("%d%d",&N,&M);
	scanf("%d",&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&w[i]);
	Bcc_cnt=N;
	for (int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		jt1(u,v);
		jt1(v,u);
	}
	cout<<Bcc_cnt<<endl;
	Tarjan(1),dfs1(1,0),dfc=0,dfs2(1,0,1);
	for (int i=1;i<=N;i++)
		if (fa[i]) S[fa[i]].insert(w[i]);
	for (int i=N+1;i<=Bcc_cnt;i++)
		w[i]=*S[i].begin();
	Build(1,1,Bcc_cnt);

	while (Q--){
		char opt[3];int x,y;
		scanf("%s%d%d",opt,&x,&y);
		if (*opt=='C'){
			Modify(1,1,Bcc_cnt,dfn[x],y);
			if (fa[x]){
				int u=fa[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();
					Modify(1,1,Bcc_cnt,dfn[u],w[u]);
				}
			}
			w[x]=y;
		}
		else{
			int Ans=1e9+7;
			while (top[x]!=top[y]){
				if (dep[top[x]]<dep[top[y]]) swap(x,y);
			Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
			x=fa[top[x]];
		  }
		  if (dfn[x]>dfn[y]) swap(x,y);
		  Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
		  if (x>N) Ans=min(Ans,w[fa[x]]);
		  printf("%d\n",Ans);
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
int cnt1,nex1[100005],las1[1000005],Arrive1[1000005],cnt2,nex2[100005],las2[10005],Arrive2[100005];
int N,M,Q,Bcc_cnt;
int w[200005];
multiset<int> S[200005];
int dfn[200005],Low[200005],Timew;
int stk[200005],tp;
void jt1(int x,int y){
	cnt1++;
	nex1[cnt1]=las1[x];
	las1[x]=cnt1;
	Arrive1[cnt1]=y;
}
void jt2(int x,int y){
	cnt2++;
	nex2[cnt2]=las2[x];
	las2[x]=cnt2;
	Arrive2[cnt2]=y;
}
void Tarjan(int Now){
	Low[Now]=dfn[Now]=++Timew;
	stk[++tp]=Now;
	for (int i=las1[Now];i;i=nex1[i]){
		if (!dfn[Arrive1[i]]){
			Tarjan(Arrive1[i]);
			Low[Now]=min(Low[Now],Low[Arrive1[i]]);
			if (Low[Now]==dfn[Now]){
				++Bcc_cnt;
				for (int x=0;x!=Arrive1[i];--tp){
					x=stk[tp];
					jt2(Bcc_cnt,x);
					jt2(x,Bcc_cnt);
				}
				jt2(Bcc_cnt,Now);
				jt2(Now,Bcc_cnt);
			}
		}
		else Low[Now]=min(Low[Now],dfn[Arrive1[i]]);
	}
}
int idf[100005],fa[1000005],Siz[1000005],dep[100005],Son[100005],top[100005],dfc;
void dfs1(int Now,int Fa){
	fa[Now]=Fa;dep[Now]=dep[Fa]+1;Siz[Now]=1;
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa){
			dfs1(Arrive2[i],Now);
			Siz[Now]+=Siz[Arrive2[i]];
			if (Siz[Son[Now]]<Siz[Arrive2[i]]) Son[Now]=Arrive2[i];
		}
}
void dfs2(int Now,int Fa,int tp){
	dfn[Now]=++dfc,idf[dfc]=Now,top[Now]=tp;
	if (Son[Now]) dfs2(Son[Now],Now,tp);
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa&&Arrive2[i]!=Son[Now])
			dfs2(Arrive2[i],Now,Arrive2[i]);
}
int Tree[1000005];
void Build(int Now,int l,int r){
	if (l==r) {Tree[Now]=w[idf[l]]; return;}
	int mid=(l+r)>>1;
	Build(Now<<1,l,mid),Build(Now<<1|1,mid+1,r);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
void Modify(int Now,int l,int r,int Pos,int x){
	if (l==r) {Tree[Now]=x;return;}
	int mid=(l+r)>>1;
	if (Pos<=mid) Modify(Now<<1,l,mid,Pos,x);
	else Modify(Now<<1|1,mid+1,r,Pos,x);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
int query(int Now,int l,int r,int L,int R){
	if (r<L||l>R) return 1e9;
	if (L<=l&&r<=R) return Tree[Now];
	int mid=(l+r)>>1;
	return min(query(Now<<1,l,mid,L,r),query(Now<<1|1,mid+1,r,L,R));
}
int main(){
	scanf("%d%d",&N,&M);
	scanf("%d",&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&w[i]);
	Bcc_cnt=N;
	for (int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		jt1(u,v);
		jt1(v,u);
	}
	Tarjan(1),dfs1(1,0),dfc=0,dfs2(1,0,1);
	for (int i=1;i<=N;i++)
		if (fa[i]) S[fa[i]].insert(w[i]);
	for (int i=N+1;i<=Bcc_cnt;i++)
		w[i]=*S[i].begin();
	Build(1,1,Bcc_cnt);

	while (Q--){
		char opt[3];int x,y;
		scanf("%s%d%d",opt,&x,&y);
		if (*opt=='C'){
			Modify(1,1,Bcc_cnt,dfn[x],y);
			if (fa[x]){
				int u=fa[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();
					Modify(1,1,Bcc_cnt,dfn[u],w[u]);
				}
			}
			w[x]=y;
		}
		else{
			int Ans=1e9+7;
			while (top[x]!=top[y]){
				if (dep[top[x]]<dep[top[y]]) swap(x,y);
			Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
			x=fa[top[x]];
		  }
		  if (dfn[x]>dfn[y]) swap(x,y);
		  Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
		  if (x>N) Ans=min(Ans,w[fa[x]]);
		  printf("%d\n",Ans);
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
int cnt1,nex1[100005],las1[1000005],Arrive1[1000005],cnt2,nex2[100005],las2[10005],Arrive2[100005];
int N,M,Q,Bcc_cnt;
int w[200005];
multiset<int> S[200005];
int dfn[200005],Low[200005],Timew;
int stk[200005],tp;
void jt1(int x,int y){
	cnt1++;
	nex1[cnt1]=las1[x];
	las1[x]=cnt1;
	Arrive1[cnt1]=y;
}
void jt2(int x,int y){
	cnt2++;
	nex2[cnt2]=las2[x];
	las2[x]=cnt2;
	Arrive2[cnt2]=y;
}
void Tarjan(int Now){
	Low[Now]=dfn[Now]=++Timew;
	stk[++tp]=Now;
	for (int i=las1[Now];i;i=nex1[i]){
		if (!dfn[Arrive1[i]]){
			Tarjan(Arrive1[i]);
			Low[Now]=min(Low[Now],Low[Arrive1[i]]);
			if (Low[Now]==dfn[Now]){
				++Bcc_cnt;
				for (int x=0;x!=Arrive1[i];--tp){
					x=stk[tp];
					jt2(Bcc_cnt,x);
					jt2(x,Bcc_cnt);
				}
				jt2(Bcc_cnt,Now);
				jt2(Now,Bcc_cnt);
			}
		}
		else Low[Now]=min(Low[Now],dfn[Arrive1[i]]);
	}
}
int idf[100005],fa[1000005],Siz[1000005],dep[100005],Son[100005],top[100005],dfc;
void dfs1(int Now,int Fa){
	fa[Now]=Fa;dep[Now]=dep[Fa]+1;Siz[Now]=1;
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa){
			dfs1(Arrive2[i],Now);
			Siz[Now]+=Siz[Arrive2[i]];
			if (Siz[Son[Now]]<Siz[Arrive2[i]]) Son[Now]=Arrive2[i];
		}
}
void dfs2(int Now,int Fa,int tp){
	dfn[Now]=++dfc,idf[dfc]=Now,top[Now]=tp;
	if (Son[Now]) dfs2(Son[Now],Now,tp);
	for (int i=las2[Now];i;i=nex2[i])
		if (Arrive2[i]!=Fa&&Arrive2[i]!=Son[Now])
			dfs2(Arrive2[i],Now,Arrive2[i]);
}
int Tree[1000005];
void Build(int Now,int l,int r){
	if (l==r) {Tree[Now]=w[idf[l]]; return;}
	int mid=(l+r)>>1;
	Build(Now<<1,l,mid),Build(Now<<1|1,mid+1,r);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
void Modify(int Now,int l,int r,int Pos,int x){
	if (l==r) {Tree[Now]=x;return;}
	int mid=(l+r)>>1;
	if (Pos<=mid) Modify(Now<<1,l,mid,Pos,x);
	else Modify(Now<<1|1,mid+1,r,Pos,x);
	Tree[Now]=min(Tree[Now<<1],Tree[Now<<1|1]);
}
int query(int Now,int l,int r,int L,int R){
	if (r<L||l>R) return 1e9;
	if (L<=l&&r<=R) return Tree[Now];
	int mid=(l+r)>>1;
	return min(query(Now<<1,l,mid,L,R),query(Now<<1|1,mid+1,r,L,R));
}
int main(){
	scanf("%d%d",&N,&M);
	scanf("%d",&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&w[i]);
	Bcc_cnt=N;
	for (int i=1;i<=M;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		jt1(u,v);
		jt1(v,u);
	}
	Tarjan(1),dfs1(1,0),dfc=0,dfs2(1,0,1);
	for (int i=1;i<=N;i++)
		if (fa[i]) S[fa[i]].insert(w[i]);
	for (int i=N+1;i<=Bcc_cnt;i++)
		w[i]=*S[i].begin();
	Build(1,1,Bcc_cnt);
	while (Q--){
		char opt[3];int x,y;
		scanf("%s%d%d",opt,&x,&y);
		if (*opt=='C'){
			Modify(1,1,Bcc_cnt,dfn[x],y);
			if (fa[x]){
				int u=fa[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();
					Modify(1,1,Bcc_cnt,dfn[u],w[u]);
				}
			}
			w[x]=y;
		}
		else{
			int Ans=1e9+7;
			while (top[x]!=top[y]){
				if (dep[top[x]]<dep[top[y]]) swap(x,y);
			Ans=min(Ans,query(1,1,Bcc_cnt,dfn[top[x]],dfn[x]));
			x=fa[top[x]];
		  }
		  if (dfn[x]>dfn[y]) swap(x,y);
		  Ans=min(Ans,query(1,1,Bcc_cnt,dfn[x],dfn[y]));
		  if (x>N) Ans=min(Ans,w[fa[x]]);
		  printf("%d\n",Ans);
		}
	}
}


#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;
}