#include <bits/stdc++.h>   using namespace std;   struct superset {     multiset<int> m;     void insert(int x) { m.insert(x); }     void erase(int x) { m.erase(m.find(x)); }     int query() { return *m.begin(); }   };   int n, m;   int val[65536 * 4];   superset cl[65536 * 4];   vector<int> g[65536 * 4];   vector<int> lis[65536 * 4];   int dfn[65536 * 4];   int DFN;   int low[65536 * 4];   int st[65536 * 4], stsiz;   int tot;   vector<int> v[65536 * 4];   void addedge(int x, int y) {     v[x].push_back(y);     v[y].push_back(x);   }   void tarjan(int x, int p) {     st[++stsiz] = x;     dfn[x] = low[x] = ++DFN;     for (int i = 0; i < g[x].size(); i++) {       int y = g[x][i];       if (y == p) continue;       if (!dfn[y]) {         tarjan(y, x);         if (low[y] >= dfn[x]) {           ++tot;           while (st[stsiz] != y) lis[tot].push_back(st[stsiz--]);           stsiz--;           lis[tot].push_back(y);           lis[tot].push_back(x);           for (int j = 0; j < lis[tot].size(); j++) addedge(lis[tot][j], tot);         }         low[x] = min(low[x], low[y]);       } else         low[x] = min(low[x], dfn[y]);     }   }   struct segmenttree {     int tree[65536 * 4 * 2 + 10];     void up(int id) { tree[id] = min(tree[id << 1], tree[id << 1 | 1]); }     void update(int x, int y) {       x = x + 65536 * 4 - 1;       tree[x] = y;       x = x / 2;       while (x) up(x), x = x / 2;     }     int query(int a, int b, int l, int r, int id) {       if (l >= a and r <= b) return tree[id];       if (b <= (l + r) / 2)         return query(a, b, l, (l + r) / 2, id << 1);       else if (a > (l + r) / 2)         return query(a, b, (l + r) / 2 + 1, r, id << 1 | 1);       else         return min(query(a, b, l, (l + r) / 2, id << 1),                    query(a, b, (l + r) / 2 + 1, r, id << 1 | 1));     }     int query(int a, int b) { return query(a, b, 1, 65536 * 4, 1); }   } trcyx;   int pa[65536 * 4];   int son[65536 * 4];   int siz[65536 * 4];   int lead[65536 * 4];   int len[65536 * 4];   int dep[65536 * 4];   void dfs1(int x, int p) {     siz[x] = 1;     dep[x] = dep[p] + 1;     for (int i = 0; i < v[x].size(); i++) {       if (v[x][i] == p) continue;       dfs1(v[x][i], x);       siz[x] += siz[v[x][i]];       if (siz[v[x][i]] > siz[son[x]]) son[x] = v[x][i];     }   }   void dfs2(int x, int p, int leader) {     dfn[x] = ++DFN;     pa[x] = p;     if (!leader) leader = x;     lead[x] = leader, len[leader]++;     if (son[x]) dfs2(son[x], x, leader);     for (int i = 0; i < v[x].size(); i++)       if (v[x][i] != son[x] and v[x][i] != p) dfs2(v[x][i], x, 0);     if (lis[x].size()) {       for (int i = 0; i < lis[x].size(); i++)         if (lis[x][i] != pa[x]) cl[x].insert(val[lis[x][i]]);       val[x] = cl[x].query();     }     trcyx.update(dfn[x], val[x]);   }   void build() {     tot = n;     tarjan(1, 0);     dfs1(1, 0);     memset(dfn, 0, sizeof(dfn));     DFN = 0;     dfs2(1, 0, 0);   }   int solve(int x, int y) {     int ans = 1e9;     while (lead[x] != lead[y]) {       if (dep[lead[x]] < dep[lead[y]]) swap(x, y);       ans = min(ans, trcyx.query(dfn[lead[x]], dfn[x]));       x = pa[lead[x]];     }     if (dfn[x] > dfn[y]) swap(x, y);     ans = min(ans, trcyx.query(dfn[x], dfn[y]));     if (lis[x].size()) ans = min(ans, val[pa[x]]);     return ans;   }   void change(int x, int y) {     if (pa[x]) {       cl[pa[x]].erase(val[x]);       cl[pa[x]].insert(y);       val[pa[x]] = cl[pa[x]].query();       trcyx.update(dfn[pa[x]], val[pa[x]]);     }     val[x] = y;     trcyx.update(dfn[x], y);   }   int main() {     int T;     scanf( %d%d%d , &n, &m, &T);     for (int i = 1; i <= n; i++) scanf( %d , &val[i]);     while (m--) {       int x, y;       scanf( %d%d , &x, &y);       g[x].push_back(y);       g[y].push_back(x);     }     build();     while (T--) {       char ctrl[10];       scanf( %s , ctrl);       int x, y;       scanf( %d%d , &x, &y);       if (ctrl[0] ==  A )         printf( %d n , solve(x, y));       else         change(x, y);     }     return 0;   }