import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        DisjointSet dsu = new DisjointSet(N+M);
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("<")) {
                    if (!dsu.addEdge(i, j+N)) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    dsu.addDegree(j+N);
                } else if (next[j].equals(">")) {
                    if (!dsu.addEdge(j+N, i)) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    dsu.addDegree(i);
                } else {
                    dsu.union(j+N, i);
                }
            }
        }
        int[] values = new int[N + M];
        for (int i = 0; i < N + M; i++) {
            if (dsu.find(i) == i && dsu.inDegree[i] == 0) {
                Queue<Integer> bfs = new ArrayDeque<>(2000);
                bfs.add(i);
                values[i] = 1;
                while (!bfs.isEmpty()) {
                    int next = bfs.poll();
                    if (values[next] > N + M) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    for (int j : dsu.getadjLists(next)) {
                        if (values[j] < values[next] + 1) {
                            values[j] = values[next] + 1;
                            bfs.add(j);
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 0; i < N+M; i++) {
            if (values[dsu.find(i)] == 0) {
                System.out.println("NO");
                System.exit(0);
            }
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    static class DisjointSet {
        int[] rank;
        int[] parent;
        int[] inDegree;
        HashSet<Integer>[] adjList;
        int size;
        static boolean[] madeParent = new boolean[2000];
        DisjointSet(int N) {
            size = N;
            rank = new int[size];
            parent = new int[size];
            adjList = new HashSet[size];
            inDegree = new int[N];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                rank[i] = 1;
                adjList[i] = new HashSet<>();
            }
        }
        public int find(int x) {
            if (parent[x] != x) {
                return parent[x] = find(parent[x]);
            }
            return x;
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void addDegree(int x) {
            inDegree[find(x)]++;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                if (rank[parX] > rank[parY]) {
                    //parX tree is larger
                    parent[parY] = parX;
                    rank[parX] += rank[parY];
                    adjList[parX].addAll(adjList[parY]);
                    adjList[parY].clear();
                    inDegree[parX] += inDegree[parY];
                }
                else {
                    //parY tree is larger or they're the same
                    parent[parX] = parY;
                    rank[parY] += rank[parX];
                    adjList[parY].addAll(adjList[parX]);
                    adjList[parX].clear();
                    inDegree[parY] += inDegree[parX];
                }
            }
        }
        public HashSet<Integer> getadjLists(int x) {
            HashSet<Integer> parentAdjList = new HashSet<>();
            if (!madeParent[x]) {
                for (int e : adjList[x]) {
                    parentAdjList.add(find(e));
                }
                adjList[x] = parentAdjList;
                madeParent[x] = true;
            }
            return adjList[x];
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    static int[] values = new int[2000];
    static int[] state = new int[2000];
    static DisjointSet dsu;
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        dsu = new DisjointSet(N+M);
        String[][] input = new String[N][M];
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("=")) {
                    dsu.union(j + N, i);
                }
            }
            input[i] = next;
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (input[i][j].equals(">")) {
                    if (!dsu.addEdge(dsu.find(i), dsu.find(j+N))) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                }
                else if (input[i][j].equals("<")) {
                    if (!dsu.addEdge(dsu.find(j+N), dsu.find(i))) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                }
            }
        }
        for (int i = 0; i < N + M; i++) {
            int temp = dsu.find(i);
            if (state[temp] != 1) {
                dfs(temp);
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 0; i < N+M; i++) {
            if (values[dsu.find(i)] == 0) {
                System.out.println("NO");
                System.exit(0);
            }
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    public static void dfs(int i) {
        if (dsu.getadjLists(i).size() == 0) {
            state[i] = 1;
            values[i] = 1;
        }
        int mx = values[i];
        state[i] = 1;
        for (int j : dsu.getadjLists(i)) {
            if (state[j] != 1) {
                dfs(j);
                mx = Math.max(values[j]+1, mx);
            }
            else {
                System.out.println("NO");
                System.exit(0);
            }
        }
        state[i] = 2;
        values[i] = mx;
        return;
    }
    static class DisjointSet {
        int[] parent;
        ArrayList<Integer>[] adjList;
        int size;
        DisjointSet(int N) {
            size = N;
            parent = new int[size];
            adjList = new ArrayList[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                adjList[i] = new ArrayList<>();
            }
        }
        public int find(int x) {
            return (parent[x] == x ? x : (parent[x] = find(parent[x])));
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                parent[parY] = parX;
            }
        }
        public ArrayList<Integer> getadjLists(int x) {
            return adjList[find(x)];
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int[][] adjList = new int[N+M][N+M];
        int[] inDegree = new int[N+M];
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("<")) {
                    adjList[i][j+N] = 1;
                    inDegree[j+N]++;
                }
                else if (next[j].equals(">")) {
                    adjList[j+N][i] = 1;
                    inDegree[i]++;
                }
                else {
                    adjList[j+N][i] = 2;
                    adjList[i][j+N] = 2;
                }
            }
        }
        int[] values = new int[N+M];
        for (int i = 0; i < N+M; i++) {
            if (inDegree[i] == 0) {
                boolean[] visited = new boolean[N+M];
                visited[i] = true;
                values[i] = 1;
                Queue<Integer> bfs = new LinkedList<Integer>();
                bfs.add(i);
                while (!bfs.isEmpty()) {
                    int next = bfs.poll();
                    for (int j = 0; j < N+M; j++) {
                        if (adjList[next][j] == 1) {
                            if (visited[j]) {
                                System.out.println("NO");
                                System.exit(0);
                            }
                            if (values[next] + 1 > values[j]) {
                                values[j] = values[next]+1;
                                visited[j] = true;
                                bfs.add(j);
                            }
                        }
                        else if (adjList[next][j] == 2) {
                            if (values[next] > values[j]) {
                                if (visited[j]) {
                                    System.out.println("NO");
                                    System.exit(0);
                                }
                                values[j] = values[next];
                                visited[j] = true;
                                bfs.add(j);
                            }
                            else if (values[next] < values[j]) {
                                if (visited[j]) {
                                    System.out.println("NO");
                                    System.exit(0);
                                }
                                values[next] = values[j];
                                visited[j] = true;
                                bfs.add(next);
                            }
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[i]+" ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[N+i] + " ");
        }
        out.println();
        out.close();
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    static int[] values = new int[2000];
    static int[] state = new int[2000];
    static DisjointSet dsu;
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        dsu = new DisjointSet(N+M);
        String[][] input = new String[N][M];
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(f.readLine());
            String[] next = st.nextToken().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("=")) {
                    dsu.union(j + N, i);
                }
            }
            input[i] = next;
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (input[i][j].equals(">")) {
                    if (!dsu.addEdge(dsu.find(i), dsu.find(j+N))) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                }
                else if (input[i][j].equals("<")) {
                    if (!dsu.addEdge(dsu.find(j+N), dsu.find(i))) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                }
            }
        }
        for (int i = 0; i < N + M; i++) {
            int temp = dsu.find(i);
            if (state[temp] != 1) {
                dfs(temp);
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 0; i < N+M; i++) {
            if (values[dsu.find(i)] == 0) {
                System.out.println("NO");
                System.exit(0);
            }
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    public static void dfs(int i) {
        if (dsu.getadjLists(i).size() == 0) {
            state[i] = 1;
            values[i] = 1;
        }
        int mx = values[i];
        state[i] = 1;
        for (int j : dsu.getadjLists(i)) {
            if (state[j] != 1) {
                dfs(j);
                mx = Math.max(values[j]+1, mx);
            }
            else {
                System.out.println("NO");
                System.exit(0);
            }
        }
        state[i] = 2;
        values[i] = mx;
        return;
    }
    static class DisjointSet {
        int[] parent;
        ArrayList<Integer>[] adjList;
        int size;
        DisjointSet(int N) {
            size = N;
            parent = new int[size];
            adjList = new ArrayList[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                adjList[i] = new ArrayList<>();
            }
        }
        public int find(int x) {
            return (parent[x] == x ? x : (parent[x] = find(parent[x])));
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                parent[parY] = parX;
            }
        }
        public ArrayList<Integer> getadjLists(int x) {
            return adjList[x];
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        DisjointSet dsu = new DisjointSet(N+M);
        String[][] input = new String[N][M];
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("=")) {
                    dsu.union(j + N, i);
                }
            }
            input[i] = next;
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (input[i][j].equals(">")) {
                    dsu.addEdge(dsu.find(j+ N), dsu.find(i));
                    dsu.addDegree(dsu.find(i));
                }
                else if (input[i][j].equals("<")) {
                    dsu.addEdge(dsu.find(i), dsu.find(j+N));
                    dsu.addDegree(dsu.find(j+N));
                }
            }
        }
        int[] values = new int[N + M];
        for (int i = 0; i < N + M; i++) {
            if (dsu.find(i) == i && dsu.inDegree[i] == 0) {
                Stack<Integer> bfs = new Stack<>();
                bfs.add(i);
                values[i] = 1;
                while (!bfs.isEmpty()) {
                    int next = bfs.pop();
                    if (values[next] > N + M) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    for (int j : dsu.getadjLists(next)) {
                        if (values[j] < values[next] + 1) {
                            values[j] = values[next] + 1;
                            bfs.add(j);
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 0; i < N+M; i++) {
            if (values[dsu.find(i)] == 0) {
                System.out.println("NO");
                System.exit(0);
            }
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    static class DisjointSet {
        int[] parent;
        int[] inDegree;
        HashSet<Integer>[] adjList;
        int size;
        DisjointSet(int N) {
            size = N;
            parent = new int[size];
            adjList = new HashSet[size];
            inDegree = new int[N];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                adjList[i] = new HashSet<>();
            }
        }
        public int find(int x) {
            if (parent[x] != x) {
                return parent[x] = find(parent[x]);
            }
            return x;
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void addDegree(int x) {
            inDegree[find(x)]++;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                parent[parY] = parX;
                inDegree[parY] += inDegree[parX];
            }
        }
        public HashSet<Integer> getadjLists(int x) {
            HashSet<Integer> parentAdjList = new HashSet<>();
            return adjList[x];
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        DisjointSet dsu = new DisjointSet(N+M);
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("<")) {
                    if (!dsu.addEdge(i, j+N)) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    dsu.addDegree(j+N);
                } else if (next[j].equals(">")) {
                    if (!dsu.addEdge(j+N, i)) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    dsu.addDegree(i);
                } else {
                    dsu.union(j+N, i);
                }
            }
        }
        int[] values = new int[N + M];
        boolean[] visited = new boolean[N+M];
        for (int i = 0; i < N + M; i++) {
            if (dsu.find(i) == i && dsu.inDegree[i] == 0) {
                Stack<Integer> bfs = new Stack<>();
                bfs.add(i);
                values[i] = 1;
                while (!bfs.isEmpty()) {
                    int next = bfs.pop();
                    if (values[next] > N + M) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    for (int j : dsu.getadjLists(next)) {
                        if (values[j] < values[next] + 1) {
                            values[j] = values[next] + 1;
                            bfs.add(j);
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 0; i < N+M; i++) {
            if (values[dsu.find(i)] == 0) {
                System.out.println("NO");
                System.exit(0);
            }
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    static class DisjointSet {
        int[] rank;
        int[] parent;
        int[] inDegree;
        HashSet<Integer>[] adjList;
        int size;
        static boolean[] madeParent = new boolean[2000];
        DisjointSet(int N) {
            size = N;
            rank = new int[size];
            parent = new int[size];
            adjList = new HashSet[size];
            inDegree = new int[N];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                rank[i] = 1;
                adjList[i] = new HashSet<>();
            }
        }
        public int find(int x) {
            if (parent[x] != x) {
                return parent[x] = find(parent[x]);
            }
            return x;
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void addDegree(int x) {
            inDegree[find(x)]++;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                if (rank[parX] > rank[parY]) {
                    //parX tree is larger
                    parent[parY] = parX;
                    rank[parX] += rank[parY];
                    adjList[parX].addAll(adjList[parY]);
                    adjList[parY].clear();
                    inDegree[parX] += inDegree[parY];
                }
                else {
                    //parY tree is larger or they're the same
                    parent[parX] = parY;
                    rank[parY] += rank[parX];
                    adjList[parY].addAll(adjList[parX]);
                    adjList[parX].clear();
                    inDegree[parY] += inDegree[parX];
                }
            }
        }
        public HashSet<Integer> getadjLists(int x) {
            HashSet<Integer> parentAdjList = new HashSet<>();
            if (!madeParent[x]) {
                for (int e : adjList[x]) {
                    parentAdjList.add(find(e));
                }
                adjList[x] = parentAdjList;
            }
            return adjList[x];
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int[][] adjList = new int[N+M][N+M];
        int[] inDegree = new int[N+M];
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("<")) {
                    adjList[i][j+N] = 1;
                    inDegree[j+N]++;
                }
                else if (next[j].equals(">")) {
                    adjList[j+N][i] = 1;
                    inDegree[i]++;
                }
                else {
                    adjList[j+N][i] = 2;
                    adjList[i][j+N] = 2;
                }
            }
        }
        int[] values = new int[N+M];
        for (int i = 0; i < N+M; i++) {
            if (inDegree[i] == 0) {
                boolean[] visited = new boolean[N+M];
                visited[i] = true;
                values[i] = 1;
                Queue<Integer> bfs = new LinkedList<Integer>();
                bfs.add(i);
                while (!bfs.isEmpty()) {
                    int next = bfs.poll();
                    for (int j = 0; j < N+M; j++) {
                        if (adjList[next][j] == 1) {
                            if (visited[j] && values[next] + 1 != values[j]) {
                                System.out.println("NO");
                                System.exit(0);
                            }
                            if (values[next] + 1 > values[j]) {
                                values[j] = values[next]+1;
                                visited[j] = true;
                                bfs.add(j);
                            }
                        }
                        else if (adjList[next][j] == 2) {
                            if (values[next] > values[j]) {
                                if (visited[j]) {
                                    System.out.println("NO");
                                    System.exit(0);
                                }
                                values[j] = values[next];
                                visited[j] = true;
                                bfs.add(j);
                            }
                            else if (values[next] < values[j]) {
                                if (visited[j]) {
                                    System.out.println("NO");
                                    System.exit(0);
                                }
                                values[next] = values[j];
                                bfs.add(next);
                            }
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[i]+" ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[N+i] + " ");
        }
        out.println();
        out.close();
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int[][] adjList = new int[N+M][N+M];
        int[] inDegree = new int[N+M];
        DisjointSet equalDish = new DisjointSet(N+M);
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("<")) {
                    adjList[i][j+N] = 1;
                    inDegree[j+N]++;
                }
                else if (next[j].equals(">")) {
                    adjList[j+N][i] = 1;
                    inDegree[i]++;
                }
                else {
                    equalDish.union(j+N, i);
                    adjList[j+N][i] = 2;
                    adjList[i][j+N] = 2;
                }
            }
        }
        int[] values = new int[N+M];
        Arrays.fill(values, 1);
        for (int i = 0; i < N+M; i++) {
            if (inDegree[i] == 0) {
                boolean[] visited = new boolean[N+M];
                visited[i] = true;
                Queue<Integer> bfs = new LinkedList<Integer>();
                bfs.add(i);
                while (!bfs.isEmpty()) {
                    int next = bfs.poll();
                    int max = 0;
                    for (int val : equalDish.getEquals(next)) {
                        max = Math.max(max, values[val]);
                    }
                    for (int val : equalDish.getEquals(next)) {
                        if (values[val] != max) {
                            values[val] = max;
//                            bfs.add(val);
                        }
                        visited[val] = true;
                    }
                    for (int j = 0; j < N+M; j++) {
                        if (adjList[next][j] == 1) {
                            if (visited[j] && values[next] + 1 != values[j]) {
                                System.out.println("NO");
                                System.exit(0);
                            }
                            if (values[next] + 1 > values[j]) {
                                values[j] = values[next]+1;
                                visited[j] = true;
                                bfs.add(j);
                            }
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[i]+" ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[N+i] + " ");
        }
        out.println();
        out.close();
    }
    static class DisjointSet {
        int[] rank;
        int[] parent;
        HashSet<Integer>[] equal;
        int size;
        DisjointSet(int N) {
            size = N;
            rank = new int[size];
            parent = new int[size];
            equal = new HashSet[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                rank[i] = 1;
                equal[i] = new HashSet<>();
                equal[i].add(i);
            }
        }
        public int find(int x) {
            if (parent[x] != x) {
                return parent[x] = find(parent[x]);
            }
            return x;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                if (rank[parX] > rank[parY]) {
                    //parX tree is larger
                    parent[parY] = parX;
                    rank[parX] += rank[parY];
                    equal[parX].addAll(equal[parY]);
                }
                else {
                    //parY tree is larger or they're the same
                    parent[parX] = parY;
                    rank[parY] += rank[parX];
                    equal[parY].addAll(equal[parX]);
                }
            }
        }
        public HashSet<Integer> getEquals(int x) {
            return equal[find(x)];
        }
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        int[][] adjList = new int[N+M][N+M];
        int[] inDegree = new int[N+M];
        DisjointSet equalDish = new DisjointSet(N+M);
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("<")) {
                    adjList[i][j+N] = 1;
                    inDegree[j+N]++;
                }
                else if (next[j].equals(">")) {
                    adjList[j+N][i] = 1;
                    inDegree[i]++;
                }
                else {
                    equalDish.union(j+N, i);
                    adjList[j+N][i] = 2;
                    adjList[i][j+N] = 2;
                }
            }
        }
        int[] values = new int[N+M];
        Arrays.fill(values, 1);
        for (int i = 0; i < N+M; i++) {
            if (inDegree[i] == 0) {
                boolean[] visited = new boolean[N+M];
                visited[i] = true;
                Queue<Integer> bfs = new LinkedList<Integer>();
                bfs.add(i);
                while (!bfs.isEmpty()) {
                    int next = bfs.poll();
                    if (bfs.size() > N + M || values[next] > N + M) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                    int max = 0;
                    for (int val : equalDish.getEquals(next)) {
                        max = Math.max(max, values[val]);
                    }
                    for (int val : equalDish.getEquals(next)) {
                        if (values[val] != max) {
                            values[val] = max;
                            bfs.add(val);
                        }
                        visited[val] = true;
                    }
                    for (int j = 0; j < N+M; j++) {
                        if (adjList[next][j] == 1) {
                            if (values[next] + 1 > values[j]) {
                                values[j] = values[next]+1;
                                bfs.add(j);
                            }
                        }
                    }
                }
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[i]+" ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[N+i] + " ");
        }
        out.println();
        out.close();
    }
    static class DisjointSet {
        int[] rank;
        int[] parent;
        HashSet<Integer>[] equal;
        int size;
        DisjointSet(int N) {
            size = N;
            rank = new int[size];
            parent = new int[size];
            equal = new HashSet[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                rank[i] = 1;
                equal[i] = new HashSet<>();
                equal[i].add(i);
            }
        }
        public int find(int x) {
            if (parent[x] != x) {
                return parent[x] = find(parent[x]);
            }
            return x;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                if (rank[parX] > rank[parY]) {
                    //parX tree is larger
                    parent[parY] = parX;
                    rank[parX] += rank[parY];
                    equal[parX].addAll(equal[parY]);
                }
                else {
                    //parY tree is larger or they're the same
                    parent[parX] = parY;
                    rank[parY] += rank[parX];
                    equal[parY].addAll(equal[parX]);
                }
            }
        }
        public HashSet<Integer> getEquals(int x) {
            return equal[find(x)];
        }
    }

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    static int[] values = new int[2000];
    static int[] state = new int[2000];
    static DisjointSet dsu;
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        dsu = new DisjointSet(N+M);
        String[][] input = new String[N][M];
        for (int i = 0; i < N; i++) {
            String[] next = f.readLine().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("=")) {
                    dsu.union(j + N, i);
                }
            }
            input[i] = next;
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (input[i][j].equals(">")) {
                    if (!dsu.addEdge(dsu.find(i), dsu.find(j+N))) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                }
                else if (input[i][j].equals("<")) {
                    if (!dsu.addEdge(dsu.find(j+N), dsu.find(i))) {
                        System.out.println("NO");
                        System.exit(0);
                    }
                }
            }
        }
        for (int i = 0; i < N + M; i++) {
            if (state[i] != 1) {
                dfs(i);
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        for (int i = 0; i < N+M; i++) {
            if (values[dsu.find(i)] == 0) {
                System.out.println("NO");
                System.exit(0);
            }
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    public static int dfs(int i) {
        if (dsu.getadjLists(i).size() == 0) {
            return values[i] = 1;
        }
        int mx = values[i];
        state[i] = 1;
        for (int j : dsu.getadjLists(i)) {
            if (state[j] != 1) {
                mx = Math.max(dfs(j) + 1, mx);
            }
            else {
                System.out.println("NO");
                System.exit(0);
            }
        }
        state[i] = 2;
        values[i] = mx;
        return values[i];
    }
    static class DisjointSet {
        int[] parent;
        int[] inDegree;
        HashSet<Integer>[] adjList;
        int size;
        DisjointSet(int N) {
            size = N;
            parent = new int[size];
            adjList = new HashSet[size];
            inDegree = new int[N];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                adjList[i] = new HashSet<>();
            }
        }
        public int find(int x) {
            if (parent[x] != x) {
                return parent[x] = find(parent[x]);
            }
            return x;
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void addDegree(int x) {
            inDegree[find(x)]++;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                parent[parY] = parX;
                inDegree[parY] += inDegree[parX];
            }
        }
        public HashSet<Integer> getadjLists(int x) {
            return adjList[find(x)];
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;

public class GourmetChoice {
    static int[] values = new int[2000];
    static color[] state = new color[2000];
    static DisjointSet dsu;
    public static void main(String[] args) throws IOException {
        BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(f.readLine());
        int N = Integer.parseInt(st.nextToken());
        int M = Integer.parseInt(st.nextToken());
        dsu = new DisjointSet(N+M);
        String[][] input = new String[N][M];
        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(f.readLine());
            String[] next = st.nextToken().split("");
            for (int j = 0; j < M; j++) {
                if (next[j].equals("=")) {
                    dsu.union(j + N, i);
                }
            }
            input[i] = next;
        }
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                if (input[i][j].equals(">")) {
                    dsu.addEdge(dsu.find(i), dsu.find(j+N));
                }
                else if (input[i][j].equals("<")) {
                    dsu.addEdge(dsu.find(j+N), dsu.find(i));
                }
            }
        }
        for (int i = 0; i <2000; i++) {
            state[i] = color.blank;
        }
        for (int i = 0; i < N + M; i++) {
            int temp = dsu.find(i);
            if (state[temp] == color.blank) {
                dfs(temp);
            }
        }
        PrintWriter out = new PrintWriter(System.out);
        if (!ok) {
                System.out.println("NO");
                System.exit(0);
        }
        out.println("YES");
        for (int i = 0; i < N; i++) {
            out.print(values[dsu.find(i)] + " ");
        }
        out.println();
        for (int i = 0; i < M; i++) {
            out.print(values[dsu.find(N+i)] + " ");
        }
        out.println();
        out.close();
    }
    static boolean ok = true;
    public static void dfs(int i) {
        if (dsu.getadjLists(i).size() == 0) {
            state[i] = color.okay;
            values[i] = 1;
            return;
        }
        int mx = values[i];
        state[i] = color.progress;
        for (int j : dsu.getadjLists(i)) {
            if (!ok) return;
            if (state[j] != color.okay) dfs(j);
            mx = Math.max(mx, values[j]+1);
        }
        state[i] = color.okay;
        values[i] = mx;
    }
    static class DisjointSet {
        int[] parent;
        ArrayList<Integer>[] adjList;
        int size;
        DisjointSet(int N) {
            size = N;
            parent = new int[size];
            adjList = new ArrayList[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
                adjList[i] = new ArrayList<>();
            }
        }
        public int find(int x) {
            return (parent[x] == x ? x : (parent[x] = find(parent[x])));
        }
        public boolean addEdge(int x, int e) {
            if (find(e) == find(x)) {
                return false;
            }
            adjList[find(x)].add(e);
            return true;
        }
        public void union(int x, int y) {
            int parX = find(x);
            int parY = find(y);
            if (parX != parY) {
                parent[parY] = parX;
            }
        }
        public ArrayList<Integer> getadjLists(int x) {
            return adjList[x];
        }
    }
    enum color {
        progress, okay, blank;
    };
}


#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
typedef pair<int,int> pii;
typedef pair<lli,lli> pll;
void sc(){}
template<typename T,typename... Args>
void sc(T& a, Args&... args) {cin>>a,sc(args...);}
template<typename T>
void pr(T a){cout<<a;}
template<typename T,typename... Args>
void pr(T a, Args... args) {cout<<a<<" ",pr(args...);}
template<typename T>
void prl(T a){cout<<a<<"\n";}
template<typename T,typename... Args>
void prl(T a, Args... args) {cout<<a<<" ",prl(args...);}
template<typename T>
int sz(const T &a){return (int)a.size();}
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
const int MAXN=1e5+1;
int n,m,q;
int val[MAXN];
int finval[2*MAXN];
multiset<int> cycvals[MAXN];
struct node{
    int data,le,ri;
    struct node* left,*right;
    node(){
        data=0,le=0,ri=0;
        left=NULL,right=NULL;
    }
    int mid(){return(le+ri)/2;}
    void mt(int l, int r){
        le=l,ri=r;
        if(le!=ri){
            left=new node(),right=new node();
            left->mt(le,mid()),right->mt(mid()+1,ri);
        }
    }
    void update(int a, int am){
        if(a<le||a>ri)return;
        if(le==ri){
            data=am;
            return;
        }
        left->update(a,am),right->update(a,am);
        data=min(left->data,right->data);
    }
    int query(int l, int r){
        if(le>r||ri<l)return INT_MAX;
        if(le>=l&&ri<=r)return data;
        return min(left->query(l,r),right->query(l,r));
    }
};
vector<int> matrix[MAXN];
vector<int> fin[2*MAXN];
int ind[MAXN];
int low[MAXN];
int curind=1;
stack<int> st;
int cycleindex[MAXN];
vector<int> cyclerep;
vector<int> contains[MAXN];
int depth[2*MAXN];
int sts[2*MAXN];
int lift[2*MAXN][18];
int curcycle=1;
int cp[2*MAXN];
int cind[2*MAXN];
int chain[2*MAXN];
vector<node> hld;
void abcc(int loc, int parent){
    ind[loc]=curind;
    low[loc]=curind++;
    st.push(loc);
    for(int x:matrix[loc]){
        if(x!=parent) {
            if (!ind[x]) {
                abcc(x,loc);
                low[loc]=min(low[loc],low[x]);
                if(low[x]==ind[loc]){
                    contains[loc].push_back(curcycle);
                    cyclerep.push_back(loc);
                    while(1){
                        int cur=st.top();
                        st.pop();
                        cycleindex[cur]=curcycle;
                        if(cur==x)break;
                    }
                    curcycle++;
                }
            }
            else low[loc]=min(low[loc],ind[x]);
        }
    }
    if(low[loc]==ind[loc])st.pop();
}
int dfs(int loc, int parent, int dep){
    lift[loc][0]=parent;
    depth[loc]=dep;
    sts[loc]=1;
    for(int x:fin[loc])if(x!=parent)sts[loc]+=dfs(x,loc,dep+1);
    return sts[loc];
}
void ml(){
    rep(i,1,18){
        rep(j,1,n+curcycle){
            lift[j][i]=lift[lift[j][i-1]][i-1];
        }
    }
}
void makechains(int loc, int parent, int rep, int ind){
    if(ind==1){
        chain[loc]=sz(hld);
        hld.push_back(node());
    }
    cp[loc]=rep;
    cind[loc]=ind;
    chain[loc]=chain[rep];
    int ma=0;
    for(int x:fin[loc])if(x!=parent)ma=max(ma,sts[x]);
    for(int x:fin[loc]){
        if(x!=parent){
            if(sts[x]==ma)makechains(x,loc,rep,ind+1),ma=-1;
            else makechains(x,loc,x,1);
        }
    }
    if(ma==0)hld[chain[loc]].mt(1,ind);
    hld[chain[loc]].update(ind,finval[loc]);
}
int getlca(int a, int b){
    if(depth[a]<depth[b])swap(a,b);
    int diff=depth[a]-depth[b];
    rep(i,0,18)if(diff&(1<<i))a=lift[a][i];
    if(a==b)return a;
    for(int i=17;i>=0;i--)if(lift[a][i]!=lift[b][i])a=lift[a][i],b=lift[b][i];
    return lift[a][0];
}
int query(int loc, int stop){
    int ans=INT_MAX;
    while(loc!=lift[stop][0]){
        if(depth[cp[loc]]>=depth[stop]){
            ans=min(ans,hld[chain[loc]].query(1,cind[loc]));
            loc=lift[cp[loc]][0];
        }
        else{
            ans=min(ans,hld[chain[loc]].query(cind[stop],cind[loc]));
            loc=lift[stop][0];
        }
    }
    return ans;
}
int main(){
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    sc(n,m,q);
    rep(i,1,n+1)sc(val[i]);
    int a,b;
    cyclerep.push_back(0);
    rep(i,0,m){
        sc(a,b);
        matrix[a].push_back(b);
        matrix[b].push_back(a);
    }
    abcc(1,0);
    rep(i,1,n+1){
        finval[i]=val[i];
        for(int x:matrix[i]){
            if((cycleindex[x]!=cycleindex[i])||cycleindex[i]==0){
                if(cyclerep[cycleindex[x]]!=i&&cyclerep[cycleindex[i]]!=x)fin[i].push_back(x);
            }
        }
        if(cycleindex[i]!=0){
            cycvals[cycleindex[i]].insert(finval[i]);
            fin[i].push_back(n+cycleindex[i]);
            fin[n+cycleindex[i]].push_back(i);
        }
        for(int x:contains[i]){
            fin[i].push_back(n+x);
            fin[n+x].push_back(i);
        }
    }
    rep(i,1,curcycle){
        finval[i+n]=*cycvals[i].begin();
    }
    dfs(1,0,0);
    ml();
    makechains(1,0,1,1);
    char c;
    while(q--){
        sc(c,a,b);
        if(c=='C'){
            if(cycleindex[a]){
                cycvals[cycleindex[a]].erase(cycvals[cycleindex[a]].find(finval[a]));
                cycvals[cycleindex[a]].insert(b);
                hld[chain[cycleindex[a]]].update(cind[cycleindex[a]],*cycvals[cycleindex[a]].begin());
            }
            hld[chain[a]].update(cind[a],b);
            finval[a]=b;
        }
        else{
            int lca=getlca(a,b);
            int ans=min(query(a,lca),query(b,lca));
            if(lca>n)ans=min(ans,finval[cyclerep[lca-n]]);
            prl(ans);
        }
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
typedef pair<int,int> pii;
typedef pair<lli,lli> pll;
void sc(){}
template<typename T,typename... Args>
void sc(T& a, Args&... args) {cin>>a,sc(args...);}
template<typename T>
void pr(T a){cout<<a;}
template<typename T,typename... Args>
void pr(T a, Args... args) {cout<<a<<" ",pr(args...);}
template<typename T>
void prl(T a){cout<<a<<"\n";}
template<typename T,typename... Args>
void prl(T a, Args... args) {cout<<a<<" ",prl(args...);}
template<typename T>
int sz(const T &a){return (int)a.size();}
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
const int MAXN=1e5+1;
int n,m,q;
int val[2*MAXN];
multiset<int> cycvals[MAXN];
struct node{
    int data,le,ri;
    struct node* left,*right;
    node(){
        data=0,le=0,ri=0;
        left=NULL,right=NULL;
    }
    int mid(){return(le+ri)/2;}
    void mt(int l, int r){
        le=l,ri=r;
        if(le!=ri){
            left=new node(),right=new node();
            left->mt(le,mid()),right->mt(mid()+1,ri);
        }
    }
    void update(int a, int am){
        if(a<le||a>ri)return;
        if(le==ri){
            data=am;
            return;
        }
        left->update(a,am),right->update(a,am);
        data=min(left->data,right->data);
    }
    int query(int l, int r){
        if(le>r||ri<l)return INT_MAX;
        if(le>=l&&ri<=r)return data;
        return min(left->query(l,r),right->query(l,r));
    }
};
vector<int> matrix[MAXN];
vector<int> fin[2*MAXN];
int ind[MAXN];
int low[MAXN];
int curind=1;
stack<int> st;
int cycleindex[MAXN];
vector<int> cyclerep;
vector<int> contains[MAXN];
int depth[2*MAXN];
int sts[2*MAXN];
int lift[2*MAXN][18];
int curcycle=1;
int cp[2*MAXN];
int cind[2*MAXN];
int chain[2*MAXN];
vector<node> hld;
void abcc(int loc, int parent){
    ind[loc]=curind;
    low[loc]=curind++;
    st.push(loc);
    for(int x:matrix[loc]){
        if(x!=parent) {
            if (!ind[x]) {
                abcc(x,loc);
                low[loc]=min(low[loc],low[x]);
                if(low[x]==ind[loc]){
                    contains[loc].push_back(curcycle);
                    cyclerep.push_back(loc);
                    while(1){
                        int cur=st.top();
                        st.pop();
                        cycleindex[cur]=curcycle;
                        if(cur==x)break;
                    }
                    curcycle++;
                }
            }
            else low[loc]=min(low[loc],ind[x]);
        }
    }
    if(low[loc]==ind[loc])st.pop();
}
int dfs(int loc, int parent, int dep){
    lift[loc][0]=parent;
    depth[loc]=dep;
    sts[loc]=1;
    for(int x:fin[loc])if(x!=parent)sts[loc]+=dfs(x,loc,dep+1);
    return sts[loc];
}
void ml(){
    rep(i,1,18){
        rep(j,1,n+curcycle){
            lift[j][i]=lift[lift[j][i-1]][i-1];
        }
    }
}
void makechains(int loc, int parent, int rep, int ind){
    if(ind==1){
        chain[loc]=sz(hld);
        hld.push_back(node());
    }
    cp[loc]=rep;
    cind[loc]=ind;
    chain[loc]=chain[rep];
    int ma=0;
    for(int x:fin[loc])if(x!=parent)ma=max(ma,sts[x]);
    for(int x:fin[loc]){
        if(x!=parent){
            if(sts[x]==ma)makechains(x,loc,rep,ind+1),ma=-1;
            else makechains(x,loc,x,1);
        }
    }
    if(ma==0)hld[chain[loc]].mt(1,ind);
    hld[chain[loc]].update(ind,val[loc]);
}
int getlca(int a, int b){
    if(depth[a]<depth[b])swap(a,b);
    int diff=depth[a]-depth[b];
    rep(i,0,18)if(diff&(1<<i))a=lift[a][i];
    if(a==b)return a;
    for(int i=17;i>=0;i--)if(lift[a][i]!=lift[b][i])a=lift[a][i],b=lift[b][i];
    return lift[a][0];
}
int query(int loc, int stop){
    int ans=INT_MAX;
    while(loc!=lift[stop][0]){
        if(depth[cp[loc]]>=depth[stop]){
            ans=min(ans,hld[chain[loc]].query(1,cind[loc]));
            loc=lift[cp[loc]][0];
        }
        else{
            ans=min(ans,hld[chain[loc]].query(cind[stop],cind[loc]));
            loc=lift[stop][0];
        }
    }
    return ans;
}
int main(){
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    sc(n,m,q);
    rep(i,1,n+1)sc(val[i]);
    int a,b;
    cyclerep.push_back(0);
    rep(i,0,m){
        sc(a,b);
        matrix[a].push_back(b);
        matrix[b].push_back(a);
    }
    abcc(1,0);
    rep(i,1,n+1){
        for(int x:matrix[i]){
            if((cycleindex[x]!=cycleindex[i])||cycleindex[i]==0){
                if(cyclerep[cycleindex[x]]!=i&&cyclerep[cycleindex[i]]!=x)fin[i].push_back(x);
            }
        }
        if(cycleindex[i]!=0){
            cycvals[cycleindex[i]].insert(val[i]);
            fin[i].push_back(n+cycleindex[i]);
            fin[n+cycleindex[i]].push_back(i);
        }
        for(int x:contains[i]){
            fin[i].push_back(n+x);
            fin[n+x].push_back(i);
        }
    }
    rep(i,1,curcycle){
        val[i+n]=*cycvals[i].begin();
    }
    dfs(1,0,0);
    ml();
    makechains(1,0,1,1);
    char c;
    while(q--){
        sc(c,a,b);
        if(c=='C'){
            if(cycleindex[a]){
                cycvals[cycleindex[a]].erase(cycvals[cycleindex[a]].find(val[a]));
                cycvals[cycleindex[a]].insert(b);
                hld[chain[n+cycleindex[a]]].update(cind[n+cycleindex[a]],*cycvals[cycleindex[a]].begin());
            }
            hld[chain[a]].update(cind[a],b);
            val[a]=b;
        }
        else{
            int lca=getlca(a,b);
            int ans=min(query(a,lca),query(b,lca));
            if(lca>n)ans=min(ans,val[cyclerep[lca-n]]);
            prl(ans);
        }
    }
    return 0;
}


#pragma GCC optimize("2,Ofast,inline")
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int inf = 0x3f3f3f3f;

int n, m, q;

void read(int &x) {
	char c = getchar();
	x = 0;
	while (c > '9' || c < '0') c = getchar();
	while (c >='0' && c <='9')
		x = (x << 3) + (x << 1) + c - '0', c = getchar();
}

namespace Gragh2 {
	int E, V, tim;
	int fir[N], nex[N << 1], arr[N << 1];
	int val[N], tr[N << 2], fa[N], dep[N];
	int dfn[N], pos[N], son[N], siz[N], top[N];
	multiset<int> Set[N];

	void Build(int x, int l, int r) {
		if (l == r) return (void) (tr[x] = val[pos[l]]);
		int mid = (l + r) >> 1;
		Build(x << 1, l, mid);
		Build(x << 1 | 1, mid + 1, r);
		tr[x] = min(tr[x << 1], tr[x << 1 | 1]);
	}

	void Updata(int x, int l, int r, int pos, int val) {
		if (l == r) return (void) (tr[x] = val);
		int mid = (l + r) >> 1;
		if (mid >= pos)
			Updata(x << 1, l, mid, pos, val);
		if (mid < pos)
			Updata(x << 1 | 1, mid + 1, r, pos, val);
		tr[x] = min(tr[x << 1], tr[x << 1 | 1]);
	}

	int Query(int x, int l, int r, int ql, int qr) {
		if (ql <= l && r <= qr) return tr[x];
		int mid = (l + r) >> 1, ans = inf;
		if (mid >= ql)
			ans = min(ans, Query(x << 1, l, mid, ql, qr));
		if (mid < qr)
			ans = min(ans, Query(x << 1 | 1, mid + 1, r, ql, qr));
		return ans;
	}

	inline void Add_Edge(int x, int y) {
		nex[++E] = fir[x];
		fir[x] = E; arr[E] = y;
	}

	void dfs1(int x) {
		siz[x] = 1;
		for (int i = fir[x]; i; i = nex[i]) {
			if (arr[i] == fa[x]) continue;
			fa[arr[i]] = x;
			dep[arr[i]] = dep[x] + 1;
			dfs1(arr[i]);
			if (siz[arr[i]] > siz[son[x]])
				son[x] = arr[i];
			siz[x] += siz[arr[i]];
			if (x > n) Set[x].insert(val[arr[i]]);
		}
		if (x > n) {
			if (Set[x].size())
				val[x] = *Set[x].begin();
			else val[x] = inf;
		}
	}

	void dfs2(int x) {
		dfn[x] = ++tim;
		pos[tim] = x;
		if (son[x]) {
			top[son[x]] = top[x];
			dfs2(son[x]);
		}
		for (int i = fir[x]; i; i = nex[i]) {
			if (arr[i] == fa[x] || arr[i] == son[x]) continue;
			top[arr[i]] = arr[i];
			dfs2(arr[i]);
		}
	}

	int calc(int x, int y) {
		int ans = inf;
		while (top[x] != top[y]) {
			if (dep[top[x]] < dep[top[y]])
				swap(x, y);
			ans = min(ans, Query(1, 1, V, dfn[top[x]], dfn[x]));
			x = fa[top[x]];
		}
		if (dep[x] < dep[y]) swap(x, y);
		ans = min(ans, Query(1, 1, V, dfn[y], dfn[x]));
		if (y > n && fa[y]) ans = min(ans, val[fa[y]]);
		return ans;
	}

	void main() {
		top[1] = dep[1] = 1;
		dfs1(1);
		dfs2(1);
		Build(1, 1, V);
		while (q--) {
			char s[5];
			int a, b;
			scanf("%s", s + 1);
			read(a); read(b);
			if (s[1] == 'C') {
				if (fa[a]) {
					multiset<int>::iterator it = Set[fa[a]].find(val[a]);
					Set[fa[a]].erase(it);
					Set[fa[a]].insert(b);
					val[fa[a]] = *Set[fa[a]].begin();
					Updata(1, 1, V, dfn[fa[a]], val[fa[a]]);
				}
				val[a] = b;
				Updata(1, 1, V, dfn[a], val[a]);
			}
			if (s[1] == 'A') {
				int tmp = calc(a, b);
				printf("%d\n", tmp);
			}
		}
	}
}

namespace Gragh1 {
	int E, top, tim;
	int fir[N], nex[N << 1], arr[N << 1];
	int st[N], dfn[N], low[N];

	inline void Add_Edge(int x, int y) {
		nex[++E] = fir[x];
		fir[x] = E; arr[E] = y;
	}

	void dfs(int x, int fa) {
		dfn[x] = low[x] = ++tim;
		st[++top] = x;
		for (int i = fir[x]; i; i = nex[i]) {
			if (arr[i] == fa) continue;
			if (dfn[arr[i]]) low[x] = min(low[x], dfn[arr[i]]);
			else {
				dfs(arr[i], x);
				low[x] = min(low[x], low[arr[i]]);
				if (low[arr[i]] >= dfn[x]) {
					Gragh2::V++;
					Gragh2::Add_Edge(Gragh2::V, x);
					Gragh2::Add_Edge(x, Gragh2::V);
					int tmp = 0;
					do {
						tmp = st[top--];
						Gragh2::Add_Edge(Gragh2::V, tmp);
						Gragh2::Add_Edge(tmp, Gragh2::V);
					} while (tmp != arr[i]);
				}
			}
		}
	}

	void main() {
		for (int i = 1; i <= n; ++i)
			read(Gragh2::val[i]);
		for (int i = 1; i <= m; ++i) {
			int x, y;
			read(x); read(y);
			Gragh1::Add_Edge(x, y);
			Gragh1::Add_Edge(y, x);
		}
		dfs(1, 0);
	}
}

int main() {
	read(n); read(m); read(q);
	Gragh2::V = n;
	Gragh1::main();
	Gragh2::main();
	return 0;
}


#include<bits/stdc++.h>
#define N 400001
#define M 500001
using namespace std;
const int INF=1e9;
set<int> fang[N];
map<int,int> cishu[N];
int n,m,q,to1[N],Nxt[N],first1[N],dfn[N],low[N];
int to[M],nxt[M],first[M],cnt,e1,x2,fa[N];
int sum,tot=0,ss[N],heavy[N],siz[N],seg[1000001];
int pos[N],top[N],deep[N],h=0,Stack[N*10];
char ch;
void Build(int x,int y){
    to1[cnt]=y;
    Nxt[cnt]=first1[x];
    first1[x]=cnt++;
}
void insert(int x,int y){
    to[e1]=y;
    nxt[e1]=first[x];
    first[x]=e1++;
}
void tarjan(int x){
	dfn[x]=low[x]=++tot;Stack[++h]=x;
	for(int i=first1[x];i!=-1;i=Nxt[i])
	    if(!dfn[to1[i]]){
        	tarjan(to1[i]);
	    	low[x]=min(low[x],low[to1[i]]);
	    	if(dfn[x]<=low[to1[i]]){
	    		int z;sum++;
	    		do{
	    	    	z=Stack[h--];
	    	    	insert(sum,z);
					insert(z,sum);
				}while(z!=to1[i]);
				insert(sum,x);insert(x,sum);
			}
		}else low[x]=min(low[x],dfn[to1[i]]);
}
void dfs(int o,int p){
	siz[o]=1;deep[o]=deep[p]+1;fa[o]=p;
	for(int i=first[o];i!=-1;i=nxt[i])
	    if(to[i]!=p){
	    	dfs(to[i],o);siz[o]+=siz[to[i]];
	    	if(siz[to[i]]>siz[heavy[o]]) heavy[o]=to[i];
		}
}
void dfs1(int o,int p){
	pos[o]=++x2;
	if(heavy[o]>0){
	    top[heavy[o]]=top[o];dfs1(heavy[o],o);
	    for(int i=first[o];i!=-1;i=nxt[i])
	        if((to[i]!=p)&&(to[i]!=heavy[o])){
	        	top[to[i]]=to[i];
				dfs1(to[i],o);
			}
	}
}
void put(int o,int p,int q,int r,int s){
	if((o==q)&&(p==q)) {seg[r]=s;return;}
	int mid=(o+p)/2;
	if(q<=mid) {
	    put(o,mid,q,r*2,s);
	    seg[r]=min(seg[r*2+1],seg[r*2]);
	}else{
	    put(mid+1,p,q,r*2+1,s);
	    seg[r]=min(seg[r*2],seg[r*2+1]);
	}
}
int get(int o,int p,int q,int r,int s){
	if((o==q)&&(p==r)) return seg[s];
	int mid=(o+p)/2;
	if(r<=mid) return get(o,mid,q,r,s*2);else
	if(q>mid) return get(mid+1,p,q,r,s*2+1);else
	return min(get(o,mid,q,mid,s*2),get(mid+1,p,mid+1,r,s*2+1));
}
int gettree(int o,int p){
	int yu=INF;
	while(top[o]!=top[p]){
		if(deep[top[o]]<deep[top[p]]) {int t=o;o=p;p=t;}
		yu=min(yu,get(1,sum,pos[top[o]],pos[o],1));
		o=fa[top[o]];
	}
	if(deep[o]>deep[p]) {int t=o;o=p;p=t;}
	yu=min(yu,get(1,sum,pos[o],pos[p],1));
	if(o>n) yu=min(yu,ss[fa[o]]);
	return yu;
}
int main(){
	memset(first1,-1,sizeof(first1));
	memset(first,-1,sizeof(first));
	scanf("%d%d%d",&n,&m,&q);sum=n;
	for(int i=1;i<=n;i++) scanf("%d",&ss[i]);
	for(int i=1;i<=m;i++){
		int x,y;scanf("%d%d",&x,&y);
		Build(x,y);
		Build(y,x);
	}
	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
	deep[0]=0;dfs(1,0);top[1]=1;dfs1(1,0);
	for(int i=1;i<=n;i++)
	    if(fa[i]>0){
		    fang[fa[i]].insert(ss[i]);
		    if(!cishu[fa[i]].count(ss[i])) cishu[fa[i]][ss[i]]=0;
		    cishu[fa[i]][ss[i]]++;
		}
	for(int i=n+1;i<=sum;i++) ss[i]=*fang[i].begin();
	for(int i=0;i<=1000000;i++) seg[i]=INF+1;
	for(int i=1;i<=sum;i++) put(1,sum,pos[i],1,ss[i]);
	for(int i=1;i<=q;i++){
		int x,y;getchar();scanf("%c%d%d",&ch,&x,&y);
		if(ch=='C'){
			if(fa[x]>0){
			    cishu[fa[x]][ss[x]]--;
			    if(cishu[fa[x]][ss[x]]==0) fang[fa[x]].erase(ss[x]);
			    if(!cishu[fa[x]].count(y)) cishu[fa[x]][y]=0;
			    cishu[fa[x]][y]++;fang[fa[x]].insert(y);
			    put(1,sum,pos[fa[x]],1,(*fang[fa[x]].begin()));
			}
			put(1,sum,pos[x],1,y);ss[x]=y;
		}else cout<<gettree(x,y)<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct edge{
	int to,next;
}ed1[1000010],ed2[1000010];
int sz1,head1[200010],sz2,head2[200010],dfn[200010],low[200010],fa[200010],top[200010];
int num,st[200010],tpp,val[200010],tim,w[200010],size[200010],son[200010],A[200010],pre[200010],Min[800010],n,m,q,deep[200010];
multiset <int> s[200010];
inline void add_edge1(int from,int to)
{
	ed1[++sz1].to=to;
	ed1[sz1].next=head1[from];
	head1[from]=sz1;
}
inline void add_edge2(int from,int to)
{
	ed2[++sz2].to=to;
//	cout<<from<<' '<<to<<"$"<<endl;
	ed2[sz2].next=head2[from];
	head2[from]=sz2;
}
inline int read()
{
	char c=getchar();int x=0,flag=1;
	while(!isdigit(c)){if(c=='-') flag=-1;c=getchar();}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x*flag;
}
void tarjan(int u)
{
	dfn[u]=low[u]=++tim;
	st[++tpp]=u;
	for(int i=head1[u];i;i=ed1[i].next)
	{
		int v=ed1[i].to;
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				num++;
				add_edge2(u,num);
				add_edge2(num,u);
			//	s[num].insert(w[u]);
				val[num]=1e9;
				while(1)
				{
					int now=st[tpp--];
					add_edge2(now,num);
					add_edge2(num,now);
					s[num].insert(w[now]);
					val[num]=min(val[num],w[now]);
					if(now==v) break;
				}
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}
void dfs1(int u,int ff)
{
	fa[u]=ff,size[u]=1;
	deep[u]=deep[ff]+1;
	for(int i=head2[u];i;i=ed2[i].next)
	{
		int v=ed2[i].to;
		if(v==ff) continue;
		dfs1(v,u);
		size[u]+=size[v];
		if(size[v]>size[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int ff,int tp)
{
	top[u]=tp;
	A[u]=++tim;
	pre[tim]=u;
	if(!son[u]) return;
	dfs2(son[u],u,tp);
	for(int i=head2[u];i;i=ed2[i].next)
	{
		int v=ed2[i].to;
		if(v==ff||v==son[u]) continue;
		dfs2(v,u,v);
	}
}
void update(int root,int l,int r,int x,int k)
{

	if(l==r)
	{
		Min[root]=k;
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) update(root<<1,l,mid,x,k);
	else update(root<<1|1,mid+1,r,x,k);
	Min[root]=min(Min[root<<1],Min[root<<1|1]);
}
void modify(int x,int y)
{
	if(fa[x]&&fa[x]>n)
	{
		int ff=fa[x];
	//	cout<<*s[ff].begin()<<"^"<<endl;
		s[ff].erase(s[ff].find(val[x]));
		s[ff].insert(y);
		val[ff]=*s[ff].begin();
		//cout<<val[ff]<<"$"<<endl;
		update(1,1,num,A[ff],val[ff]);
	}
	val[x]=w[x]=y;
	update(1,1,num,A[x],val[x]);
	//cout<<Min[1]<<"(((";
}
int query(int root,int l,int r,int x,int y)
{
	if(x<=l&&y>=r) return Min[root];
	int mid=l+r>>1;
	if(y<=mid) return query(root<<1,l,mid,x,y);
	if(x>mid) return query(root<<1|1,mid+1,r,x,y);
	return min(query(root<<1,l,mid,x,y),query(root<<1|1,mid+1,r,x,y));
}
int getans(int x,int y)
{
//	cout<<x<<' '<<y;
	int ans=1e9;
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]]) swap(x,y);
		ans=min(ans,query(1,1,num,A[top[x]],A[x]));
		x=fa[top[x]];
	}
	if(deep[x]<deep[y]) swap(x,y);
//	cout<<y<<' '<<x;
//cout<<Min[1]<<"))))"<<endl;
	ans=min(ans,query(1,1,num,A[y],A[x]));
	if(y>n) ans=min(ans,val[fa[y]]);
	return ans;
}
void build(int root,int l,int r)
{
	if(l==r)
	{
		Min[root]=val[pre[l]];
		return;
	}
	int mid=l+r>>1;
	build(root<<1,l,mid);
	build(root<<1|1,mid+1,r);
	Min[root]=min(Min[root<<1],Min[root<<1|1]);
}
int main()
{
	n=read(),m=read(),q=read();
	for(int i=1;i<=n;i++) w[i]=val[i]=read();
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read();
		add_edge1(u,v);
		add_edge1(v,u);
	}
	num=n;
	tarjan(1);
	tim=0;
	dfs1(1,0);
	dfs2(1,0,1);
	build(1,1,num);
//	for(int i=1;i<=num;i++) cout<<i<<' '<<fa[i]<<"**"<<endl;
	while(q--)
	{
		char c=getchar();
		int x=read(),y=read();
		if(c=='C') modify(x,y);
		else cout<<getans(x,y)<<'\n';
		//	for(int i=1;i<=num;i++) cout<<val[i]<<' ';
		//	cout<<"**"<<endl;
	}
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct edge{
	int to,next;
}ed1[1000010],ed2[1000010];
int sz1,head1[200010],sz2,head2[200010],dfn[200010],low[200010],fa[200010],top[200010];
int num,st[200010],tpp,val[200010],tim,w[200010],size[200010],son[200010],A[200010],pre[200010],Min[800010],n,m,q,deep[200010];
multiset <int> s[200010];
inline void add_edge1(int from,int to)
{
	ed1[++sz1].to=to;
	ed1[sz1].next=head1[from];
	head1[from]=sz1;
}
inline void add_edge2(int from,int to)
{
	ed2[++sz2].to=to;
//	cout<<from<<' '<<to<<"$"<<endl;
	ed2[sz2].next=head2[from];
	head2[from]=sz2;
}
inline int read()
{
	char c=getchar();int x=0,flag=1;
	while(!isdigit(c)){if(c=='-') flag=-1;c=getchar();}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return x*flag;
}
void tarjan(int u)
{
	dfn[u]=low[u]=++tim;
	st[++tpp]=u;
	for(int i=head1[u];i;i=ed1[i].next)
	{
		int v=ed1[i].to;
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u])
			{
				num++;
				add_edge2(u,num);
				add_edge2(num,u);
				s[num].insert(w[u]);
				val[num]=1e9;
				while(1)
				{
					int now=st[tpp--];
					add_edge2(now,num);
					add_edge2(num,now);
					s[num].insert(w[now]);
					val[num]=min(val[num],w[now]);
					if(now==v) break;
				}
			}
		}
		else low[u]=min(low[u],dfn[v]);
	}
}
void dfs1(int u,int ff)
{
	fa[u]=ff,size[u]=1;
	deep[u]=deep[ff]+1;
	for(int i=head2[u];i;i=ed2[i].next)
	{
		int v=ed2[i].to;
		if(v==ff) continue;
		dfs1(v,u);
		size[u]+=size[v];
		if(size[v]>size[son[u]]) son[u]=v;
	}
}
void dfs2(int u,int ff,int tp)
{
	top[u]=tp;
	A[u]=++tim;
	pre[tim]=u;
	if(!son[u]) return;
	dfs2(son[u],u,tp);
	for(int i=head2[u];i;i=ed2[i].next)
	{
		int v=ed2[i].to;
		if(v==ff||v==son[u]) continue;
		dfs2(v,u,v);
	}
}
void update(int root,int l,int r,int x,int k)
{
	if(l==r)
	{
		Min[root]=k;
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) update(root<<1,l,mid,x,k);
	else update(root<<1|1,mid+1,r,x,k);
	Min[root]=min(Min[root<<1],Min[root<<1|1]);
}
void modify(int x,int y)
{
	if(fa[x]&&fa[x]>n)
	{
		int ff=fa[x];
		s[ff].erase(s[ff].find(val[x]));
		s[ff].insert(y);
		val[ff]=*s[ff].begin();
		update(1,1,num,A[ff],val[ff]);
	}
	val[x]=w[x]=y;
	update(1,1,num,A[x],val[x]);
}
int query(int root,int l,int r,int x,int y)
{
	if(x<=l&&y>=r) return Min[root];
	int mid=l+r>>1;
	if(y<=mid) return query(root<<1,l,mid,x,y);
	if(x>mid) return query(root<<1|1,mid+1,r,x,y);
	return min(query(root<<1,l,mid,x,y),query(root<<1|1,mid+1,r,x,y));
}
int getans(int x,int y)
{
//	cout<<x<<' '<<y;
	int ans=1e9;
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]]) swap(x,y);
		ans=min(ans,query(1,1,num,A[top[x]],A[x]));
		x=fa[top[x]];
	}
	if(deep[x]<deep[y]) swap(x,y);
//	cout<<y<<' '<<x;
	ans=min(ans,query(1,1,num,A[y],A[x]));
	if(y>n) ans=min(ans,val[fa[y]]);
	return ans;
}
void build(int root,int l,int r)
{
	if(l==r)
	{
		Min[root]=val[pre[l]];
		return;
	}
	int mid=l+r>>1;
	build(root<<1,l,mid);
	build(root<<1|1,mid+1,r);
	Min[root]=min(Min[root<<1],Min[root<<1|1]);
}
int main()
{
	n=read(),m=read(),q=read();
	for(int i=1;i<=n;i++) w[i]=val[i]=read();
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read();
		add_edge1(u,v);
		add_edge1(v,u);
	}
	num=n;
	tarjan(1);
	tim=0;
	dfs1(1,0);
	dfs2(1,0,1);
	build(1,1,num);
	while(q--)
	{
		char c=getchar();
		int x=read(),y=read();
		if(c=='C') modify(x,y);
		else cout<<getans(x,y)<<'\n';
	}
	return 0;
}


//8:29
#include<bits/stdc++.h>
#define lch k<<1
#define rch k<<1|1
using namespace std;
const int N=2e5+50,inf=0x3f3f3f3f;
inline int rd(register int x=0,register char ch=getchar(),register int f=0){
	for(;!isdigit(ch);ch=getchar()) f=ch=='-';
	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-48;
	return f?-x:x;
}
int n,m,q,B,Dfn,Bcc,eul,ans;
int w[N],head[N],to[N<<1],nxt[N<<1],dfn[N],low[N],sta[N],dep[N],f[N],top[N],siz[N],hson[N],tree[N],mn[N<<2];
vector<int> e[N];
multiset<int> Set[N];

void lnk(int x,int y){
	to[++B]=y,nxt[B]=head[x],head[x]=B;
	to[++B]=x,nxt[B]=head[y],head[y]=B;
}
void add(int k,int l,int r,int p,int v){
	if(l==r) return mn[k]=v,void();
	int mid=(l+r)>>1;
	p<=mid?add(lch,l,mid,p,v):add(rch,mid+1,r,p,v);
	mn[k]=min(mn[lch],mn[rch]);
}
void ask(int k,int l,int r,int L,int R){
	if(L<=l&&r<=R) return ans=min(ans,mn[k]),void();
	int mid=(l+r)>>1;
	if(L<=mid) ask(lch,l,mid,L,R);
	if(R>mid) ask(rch,mid+1,r,L,R);
}
void tarjan(int x){
	dfn[x]=low[x]=++Dfn;sta[++sta[0]]=x;
	for(int i=head[x];i;i=nxt[i])
		if(!dfn[to[i]]){
			tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
			if(low[to[i]]==dfn[x]){
				++Bcc;int y;
				do y=sta[sta[0]--],e[Bcc].push_back(y),e[y].push_back(Bcc);
				while(y!=to[i]);
				e[Bcc].push_back(x),e[x].push_back(Bcc);
			}
		}
		else low[x]=min(low[x],dfn[to[i]]);
}
void dfs1(int x,int prt){
	//printf("%d->%d\n",prt,x);
	dep[x]=dep[prt]+1;f[x]=prt;siz[x]=1;
	for(auto y:e[x]) if(y!=prt) dfs1(y,x),siz[x]+=siz[y],hson[x]=siz[hson[x]]>siz[y]?hson[x]:y;
}
void dfs2(int x,int u){
	top[x]=u; tree[x]=++eul;
	add(1,1,Bcc,tree[x],x<=n?w[x]:(Set[x].size()?*Set[x].begin():inf));
	if(hson[x]) dfs2(hson[x],u);
	for(auto y:e[x]) if(y!=f[x]&&y!=hson[x]) dfs2(y,y);
}
int main(){
	n=rd();m=rd();q=rd();Bcc=n;
	for(int i=1;i<=n;++i) w[i]=rd();
	for(int i=1;i<=m;++i) lnk(rd(),rd());
	for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
	dfs1(1,0);
	for(int i=1;i<=n;++i) if(f[i]>n) Set[f[i]].insert(w[i]);
	dfs2(1,1);
	while(q--){
		char ch=getchar();while(ch!='A'&&ch!='C') ch=getchar();
		int x=rd(),y=rd();
		if(ch=='A'){
			ans=inf;
			while(top[x]!=top[y]){
				if(dep[top[x]]>dep[top[y]]) ask(1,1,Bcc,tree[top[x]],tree[x]),x=f[top[x]];
				else ask(1,1,Bcc,tree[top[y]],tree[y]),y=f[top[y]];
			}
			if(dep[x]>dep[y]) swap(x,y);
			ask(1,1,Bcc,tree[x],tree[y]);
			if(x>n&&f[x]) ans=min(ans,w[f[x]]);
			printf("%d\n",ans);
		}
		else{
			add(1,1,Bcc,tree[x],y);
			if(f[x]>n){
				Set[f[x]].erase(Set[f[x]].find(w[x]));
				Set[f[x]].insert(y);
				add(1,1,Bcc,tree[f[x]],*Set[f[x]].begin());
			}
			w[x]=y;
		}
	}
}


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7,INF=1e9+7;
vector<int> G[N];
int n;
inline int read(int x=0,char c=getchar()){
	for(;c>'9'||c<'0';c=getchar());
	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
	return x;
}
namespace init{
	int head[N],to[N],nxt[N],cnt,dfn[N],low[N],tot,sta[N],top,dcc;
	inline void link(int u,int v){
		to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
	}
	void Tarjan(int x){
		dfn[x]=low[x]=++tot;sta[++top]=x;
		for(int i=head[x];i;i=nxt[i]){
			int y=to[i];
			if(!dfn[y]) {
				Tarjan(y),low[x]=min(low[x],low[y]);
				if(low[y]==dfn[x]){
					++dcc;
					while(top){
						int t=sta[top--];//cout<<t<<' '<<dcc<<endl;
						G[t].push_back(dcc),G[dcc].push_back(t);
						if(t==y) break;
					}
					G[x].push_back(dcc),G[dcc].push_back(x);
				}
			}else low[x]=min(low[x],dfn[y]);
		}
	}
}
namespace work{
	#define ls k<<1
	#define rs ls|1
	int sz[N],top[N],d[N],son[N],dfn[N],ip[N],tot,fa[N],val[N],cnt,w[N],mn[N<<2];
	bool round[N];
	multiset<int> cs[N];
	void build(int k,int l,int r){
		if(l==r) {mn[k]=val[ip[l]];return ;}
		int mid=l+r>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		mn[k]=min(mn[ls],mn[rs]);
	}
	void insert(int k,int l,int r,int x,int y){
		if(l==r) return val[x]=y,void();
		int mid=l+r>>1;
		if(x<=mid) insert(ls,l,mid,x,y);
		else insert(rs,mid+1,r,x,y);
		mn[k]=min(mn[ls],mn[rs]);
	}
	int query(int k,int l,int r,int gl,int gr){
		if(l>=gl&&r<=gr) return mn[k];
		int mid=l+r>>1,ans=INF;
		if(gl<=mid) ans=min(ans,query(ls,l,mid,gl,gr));
		if(gr>mid) ans=min(ans,query(rs,mid+1,r,gl,gr));
		return ans;
	}
	void dfs1(int x,int fx){
		sz[x]=1;round[x]=x<=n;
		for(auto y:G[x]) if(y!=fx) {
			d[y]=d[x]+1,dfs1(y,x),sz[x]+=sz[y];fa[y]=x;
			if(sz[y]>sz[son[x]]) son[x]=y;
		}
		return ;
	}
	void dfs2(int x,int fx,int tp){
		dfn[x]=++tot;ip[tot]=x;top[x]=tp;
		if(son[x]) dfs2(son[x],x,tp);
		for(auto y:G[x]) if(y!=fx&&y!=son[x]) dfs2(y,x,y);
	}
	void pre(){
		cnt=init::dcc;
		dfs1(1,0),dfs2(1,0,1);
		for(int i=1;i<=cnt;++i) if(!round[i]){
			int res=INF;
			for(auto y:G[i]) if(y!=fa[i]) res=min(res,w[y]),cs[i].insert(w[y]);
			val[i]=res;
		}else val[i]=w[i];
		build(1,1,cnt);
	}
	int query(int x,int y){
		int fx=top[x],fy=top[y],res=INF;
		while(fx!=fy){
			if(d[fx]<d[fy]) swap(fx,fy),swap(x,y);
			res=min(res,query(1,1,cnt,dfn[fx],dfn[x]));
			res=min(res,val[fa[fx]]);
			x=fa[fx],fx=top[x];
		}
		if(d[x]>d[y]) swap(x,y);
		res=min(res,query(1,1,cnt,dfn[x],dfn[y]));
		if(round[x]) return res;
		else return min(res,val[fa[x]]);
	}
	void modify(int x,int y){
		if(x!=1) cs[fa[x]].erase(cs[fa[x]].find(val[x])),cs[fa[x]].insert(val[x]=y);
		insert(1,1,cnt,dfn[x],y);
		if(x!=1) val[fa[x]]=*cs[fa[x]].begin(),insert(1,1,cnt,dfn[fa[x]],val[fa[x]]);
	}
	#undef ls
	#undef rs
}
int main(){
	int m,q;
	cin>>n>>m>>q;init::dcc=n;
	for(int i=1;i<=n;++i) work::w[i]=read();
	while(m--){
		int a=read(),b=read();
		init::link(a,b),init::link(b,a);
	}
	init::Tarjan(1);work::pre();
	while(q--){
		char opt[5];int x,y;
		scanf("%s",opt);x=read(),y=read();
		if(opt[0]=='C') work::modify(x,y);
		else printf("%d\n",work::query(x,y));
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int N=2e5+7,INF=1e9+7;
vector<int> G[N];
int n;
inline int read(int x=0,char c=getchar()){
	for(;c>'9'||c<'0';c=getchar());
	for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
	return x;
}
namespace init{
	int head[N],to[N],nxt[N],cnt,dfn[N],low[N],tot,sta[N],top,dcc;
	inline void link(int u,int v){
		to[++cnt]=v,nxt[cnt]=head[u],head[u]=cnt;
	}
	void Tarjan(int x){
		dfn[x]=low[x]=++tot;sta[++top]=x;
		for(int i=head[x];i;i=nxt[i]){
			int y=to[i];
			if(!dfn[y]) {
				Tarjan(y),low[x]=min(low[x],low[y]);
				if(low[y]==dfn[x]){
					++dcc;
					while(top){
						int t=sta[top--];//cout<<t<<' '<<dcc<<endl;
						G[t].push_back(dcc),G[dcc].push_back(t);
						if(t==y) break;
					}
					G[x].push_back(dcc),G[dcc].push_back(x);
				}
			}else low[x]=min(low[x],dfn[y]);
		}
	}
}
namespace work{
	#define ls k<<1
	#define rs ls|1
	int sz[N],top[N],d[N],son[N],dfn[N],ip[N],tot,fa[N],val[N],cnt,w[N],mn[N<<2];
	bool round[N];
	multiset<int> cs[N];
	void build(int k,int l,int r){
		if(l==r) {mn[k]=val[ip[l]];return ;}
		int mid=l+r>>1;
		build(ls,l,mid);
		build(rs,mid+1,r);
		mn[k]=min(mn[ls],mn[rs]);
	}
	void insert(int k,int l,int r,int x,int y){
		if(l==r) return mn[k]=y,void();
		int mid=l+r>>1;
		if(x<=mid) insert(ls,l,mid,x,y);
		else insert(rs,mid+1,r,x,y);
		mn[k]=min(mn[ls],mn[rs]);
	}
	int query(int k,int l,int r,int gl,int gr){
//		cout<<gl<<' '<<gr<<' '<<l<<' '<<r<<' '<<mn[k]<<endl;
		if(l>=gl&&r<=gr) return mn[k];
		int mid=l+r>>1,ans=INF;
		if(gl<=mid) ans=min(ans,query(ls,l,mid,gl,gr));
		if(gr>mid) ans=min(ans,query(rs,mid+1,r,gl,gr));
		return ans;
	}
	void dfs1(int x,int fx){
		sz[x]=1;round[x]=x<=n;
		for(auto y:G[x]) if(y!=fx) {
			d[y]=d[x]+1,dfs1(y,x),sz[x]+=sz[y];fa[y]=x;
			if(sz[y]>sz[son[x]]) son[x]=y;
		}
		return ;
	}
	void dfs2(int x,int fx,int tp){
		dfn[x]=++tot;ip[tot]=x;top[x]=tp;
		if(son[x]) dfs2(son[x],x,tp);
		for(auto y:G[x]) if(y!=fx&&y!=son[x]) dfs2(y,x,y);
	}
	void pre(){
		cnt=init::dcc;
		dfs1(1,0),dfs2(1,0,1);
		for(int i=1;i<=cnt;++i) if(!round[i]){
			int res=INF;
			for(auto y:G[i]) if(y!=fa[i]) res=min(res,w[y]),cs[i].insert(w[y]);
			val[i]=res;
		}else val[i]=w[i];
		build(1,1,cnt);
	}
	int query(int x,int y){
		int fx=top[x],fy=top[y],res=INF;
		while(fx!=fy){
			if(d[fx]<d[fy]) swap(fx,fy),swap(x,y);
			res=min(res,query(1,1,cnt,dfn[fx],dfn[x]));
			res=min(res,val[fa[fx]]);
			x=fa[fx],fx=top[x];
		}
		if(d[x]>d[y]) swap(x,y);
		res=min(res,query(1,1,cnt,dfn[x],dfn[y]));
		if(round[x]) return res;
		else return min(res,val[fa[x]]);
	}
	void modify(int x,int y){
		if(x!=1) cs[fa[x]].erase(cs[fa[x]].find(val[x])),cs[fa[x]].insert(y);
		insert(1,1,cnt,dfn[x],val[x]=y);
		if(x!=1) val[fa[x]]=*cs[fa[x]].begin(),insert(1,1,cnt,dfn[fa[x]],val[fa[x]]);
	}
	#undef ls
	#undef rs
}
int main(){
	int m,q;
	cin>>n>>m>>q;init::dcc=n;
	for(int i=1;i<=n;++i) work::w[i]=read();
	while(m--){
		int a=read(),b=read();
		init::link(a,b),init::link(b,a);
	}
	init::Tarjan(1);work::pre();
	while(q--){
		char opt[5];int x,y;
		scanf("%s",opt);x=read(),y=read();
		if(opt[0]=='C') work::modify(x,y);
		else printf("%d\n",work::query(x,y));
	}
	return 0;
}


#include<cstdlib>
#include<cstdio>
#include<queue>
using namespace std;
const int N=300010;
int n,m,Q,cnt1,cnt,mcnt,w[N<<1],q[N],top,dfncnt,low[N],dfn[N],id[N<<1],id_1[N<<1],idcnt,dep[N<<1],f[N<<1],size[N<<1],son[N<<1],tp[N<<1],segcnt,g0;
char inc[10];
struct node{int v;node *next;}pool[N<<3],*h1[N],*h[N<<1];
void add1(int u,int v)
{
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h1[u];h1[u]=p;
	q->v=u;q->next=h1[v];h1[v]=q;
}
void add(int u,int v)
{
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h[u];h[u]=p;
	q->v=u;q->next=h[v];h[v]=q;
}
struct heap
{
	priority_queue<int,vector<int>,greater<int> >pq,dl;
	void push(int x){pq.push(x);}
	void del(int x)	{dl.push(x);}
	int top(){	while(!pq.empty()&&!dl.empty()&&pq.top()==dl.top()) pq.pop(),dl.pop(); return pq.top(); }
}hp[N<<1];
void tarjan(int u)
{
	low[u]=dfn[u]=++dfncnt;
	for(node *t=h1[u];t;t=t->next)
		if(dfn[t->v]==0)
		{
			int topu=top;
			q[++top]=t->v;
			tarjan(t->v);
			low[u]=min(low[u],low[t->v]);
			if(low[t->v]>=dfn[u])
			{
				int p=++mcnt;
				for(int i=topu+1;i<=top;i++) add(p,q[i]);//,hp[p].push(w[q[i]]);
				add(p,u);//hp[p].push(w[u]);
				top=topu;
			}
		}
		else low[u]=min(low[u],dfn[t->v]);
}

void dfs1(int u,int fa)
{
	f[u]=fa;
	dep[u]=dep[fa]+1;
	size[u]=1;
	for(node *t=h[u];t;t=t->next)
		if(t->v^fa)
			dfs1(t->v,u),
			size[u]+=size[t->v],
			son[u]=size[t->v]>size[son[u]]?t->v:son[u];
}
void dfs2(int u,int fa)
{
	id_1[id[u]=++idcnt]=u;
	if(son[u]) tp[son[u]]=tp[u],dfs2(son[u],u);
	for(node *t=h[u];t;t=t->next)
		if((t->v^son[u])&&(t->v^fa))
			tp[t->v]=t->v,dfs2(t->v,u);
}
struct seg{int mn,l,r;seg *ls,*rs;}segpool[N<<2],*root;
seg* build(int l,int r)
{
	seg *t=&segpool[++segcnt];
	t->l=l;t->r=r;
	if(l==r){t->mn=w[id_1[l]];return t;}
	int mid=l+r>>1;
	t->ls=build(l,mid);
	t->rs=build(mid+1,r);
	t->mn=min(t->ls->mn,t->rs->mn);
	return t;
}
void chg(seg *t,int pos,int x)
{
	if(t->l==t->r){t->mn=x;return;}
	int mid=t->l+t->r>>1;
	if(pos<=mid) chg(t->ls,pos,x);
	else chg(t->rs,pos,x);
	t->mn=min(t->ls->mn,t->rs->mn);
}
int qry(seg *t,int l,int r)
{
	if(t->l>=l&&t->r<=r) return t->mn;
	int ans=2147483600,mid=t->l+t->r>>1;
	if(l<=mid) ans=min(ans,qry(t->ls,l,r));
	if(r>mid) ans=min(ans,qry(t->rs,l,r));
	return ans;
}

int ask(int x,int y)
{
	int ans=2147483600;
	while(tp[x]^tp[y])
	{
		if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
		ans=min(ans,qry(root,id[tp[x]],id[x])),
		x=f[tp[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	ans=min(ans,qry(root,id[y],id[x]));
	g0=y;
	return ans;
}
int rd()
{
	char cx=getchar();int ret=0;
	while(cx<'0'||cx>'9') cx=getchar();
	while(cx>='0'&&cx<='9') ret=ret*10+cx-'0',cx=getchar();
	return ret;
}

int main()
{
	freopen("tourists.in","r",stdin);
	freopen("tourists.out","w",stdout);
	scanf("%d%d%d",&n,&m,&Q);
	mcnt=n;
	for(int i=1;i<=n;i++) w[i]=rd();
	for(int i=1,x,y;i<=m;i++) x=rd(),y=rd(),add1(x,y);
	q[++top]=1;tarjan(1);
	dfs1(1,0);//dep,fa,son
	tp[1]=1;dfs2(1,0);//tp,id
	for(int i=1;i<=n;i++) if(f[i]>n) {hp[f[i]].push(w[i]);}
	for(int i=n+1;i<=mcnt;i++) { w[i]=hp[i].top();}

	root=build(1,mcnt);
	//exit(0);
	for(int i=1,x,y;i<=Q;i++)
	{
		scanf("%s%d%d",inc+1,&x,&y);
		if(inc[1]=='C')
		{
			if(f[x]>n)
			{
				hp[f[x]].del(w[x]);
				hp[f[x]].push(y);
				chg(root,id[f[x]],hp[f[x]].top());
			}
			chg(root,id[x],y);
			w[x]=y;
		}
		else
		{
			int ans=ask(x,y);
			if(g0>n) ans=min(ans,w[f[g0]]);
			printf("%d\n",ans);
		}
	}
}


#include<cstdlib>
#include<cstdio>
#include<queue>
using namespace std;
const int N=100010;
int n,m,Q,cnt1,cnt,mcnt,w[N<<1],q[N],top,dfncnt,low[N],dfn[N],id[N<<1],id_1[N<<1],idcnt,a[N<<1],dep[N<<1],st[N<<1][20],size[N<<1],son[N<<1],tp[N<<1],segcnt;
char inc[10];
struct node{int v;node *next;}pool[N<<3],*h1[N],*h[N<<1];
void add1(int u,int v)
{
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h1[u];h1[u]=p;
	q->v=u;q->next=h1[v];h1[v]=q;
}
void add(int u,int v)
{
//	printf("add %d %d\n",u,v);
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h[u];h[u]=p;
	q->v=u;q->next=h[v];h[v]=q;
}
struct heap
{
	priority_queue<int,vector<int>,greater<int> >pq,dl;
	void push(int x){pq.push(x);}
	void del(int x)
	{
		dl.push(x);
		while(!pq.empty()&&pq.top()==dl.top()) pq.pop(),dl.pop();
	}
	int top(){return pq.top();}
}hp[N<<1];
void tarjan(int u)
{
	low[u]=dfn[u]=++dfncnt;
	int topu=top;
	for(node *t=h1[u];t;t=t->next)
		if(dfn[t->v]==0)
		{
			q[++top]=t->v;
			tarjan(t->v);
			low[u]=min(low[u],low[t->v]);
			if(low[t->v]>=dfn[u])
			{
				int p=++mcnt;
				for(int i=topu;i<=top;i++) add(p,q[i]),hp[p].push(w[q[i]]);//,vt[q[i]][++vt[q[i]][0]]=p;
				//w[p]=hp[p].top();
				top=topu;
			}
		}
		else low[u]=min(low[u],dfn[t->v]);
}
int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int d=dep[x]-dep[y],k=0;d;d>>=1,k++)
		if(d&1) x=st[x][k];
	if(x==y) return x;
	for(int k=18;k>=0;k--)
		if(st[x][k]^st[y][k])
			x=st[x][k],y=st[y][k];
	return st[x][0];
}
void dfs1(int u,int fa)
{
	st[u][0]=fa;
	dep[u]=dep[fa]+1;
	size[u]=1;
	for(node *t=h[u];t;t=t->next)
		if(t->v^fa)
			dfs1(t->v,u),
			size[u]+=size[t->v],
			son[u]=size[t->v]>size[son[u]]?t->v:son[u];
}
void dfs2(int u,int fa)
{
	a[id[u]=++idcnt]=w[u];
	id_1[idcnt]=u;
	if(son[u]) tp[son[u]]=tp[u],dfs2(son[u],u);
	for(node *t=h[u];t;t=t->next)
		if((t->v^son[u])&&(t->v^fa))
			tp[t->v]=t->v,dfs2(t->v,u);
}
struct seg{int mn,l,r;seg *ls,*rs;}segpool[N<<2],*root;
seg* build(int l,int r)
{
	seg *t=&segpool[++segcnt];
	t->l=l;t->r=r;
	if(l==r){t->mn=w[id_1[l]];return t;}
	int mid=l+r>>1;
	t->ls=build(l,mid);
	t->rs=build(mid+1,r);
	t->mn=min(t->ls->mn,t->rs->mn);
	return t;
}
void chg(seg *t,int pos,int x)
{
	if(t->l==t->r){t->mn=x;return;}
	int mid=t->l+t->r>>1;
	if(pos<=mid) chg(t->ls,pos,x);
	else chg(t->rs,pos,x);
	t->mn=min(t->ls->mn,t->rs->mn);
}
int qry(seg *t,int l,int r)
{
	//if(t==root) printf("qry %d %d\n",l,r);
	if(t->l>=l&&t->r<=r) return t->mn;
	int ans=2147483600,mid=t->l+t->r>>1;
	if(l<=mid) ans=min(ans,qry(t->ls,l,r));
	if(r>mid) ans=min(ans,qry(t->rs,l,r));
	//printf("qry       %d %d   %d %d  = %d\n",t->l,t->r,l,r,ans);
	return ans;
}

int ask(int x,int g)
{
	int ans=2147483600;
	while(tp[x]^tp[g])
		ans=min(ans,qry(root,id[tp[x]],id[x])),
		x=st[tp[x]][0];
	ans=min(ans,qry(root,id[g],id[x]));
	return ans;
}

int main()
{
	scanf("%d%d%d",&n,&m,&Q);
	mcnt=n;
	for(int i=1;i<=n;i++) scanf("%d",&w[i]);//,vt[i].push_back(0);
	for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),add1(x,y);
	q[++top]=1;tarjan(1);
	/*for(int i=1;i<=n;i++)
	{
		printf("vt[%d]  ( %d ): ",i,w[i]);
		for(int j=1;j<=vt[i][0];j++) printf("%d ",vt[i][j]);
		printf("\n");
	}
	for(int i=1;i<=mcnt;i++) printf("%d %d  \n",i,w[i]);
	*/
	dfs1(1,0);//dep,fa,son
	tp[1]=1;dfs2(1,0);//tp,id
	for(int k=1;k<19;k++)
		for(int i=1;i<=mcnt;i++)
			st[i][k]=st[st[i][k-1]][k-1];

	for(int i=n+1;i<=mcnt;i++) hp[i].del(w[st[i][0]]),w[i]=hp[i].top();
	//for(int i=1;i<=mcnt;i++) printf("== %d %d %d  %d\n",i,w[i],tp[i],id[i]);
	root=build(1,mcnt);
	for(int i=1,x,y;i<=Q;i++)
	{
		scanf("%s%d%d",inc+1,&x,&y);
		if(inc[1]=='C')
		{
			if(st[x][0]>n)
			{
				hp[st[x][0]].del(w[x]);
				hp[st[x][0]].push(y);
				chg(root,id[st[x][0]],hp[st[x][0]].top());
			}
			chg(root,id[x],y);
			w[x]=y;
		}
		else
		{
			int g=lca(x,y),ans;
			ans=min(ask(y,g),ask(x,g));
			//printf("g= %d  ans=%d\n",g,ans);
			if(g>n) ans=min(ans,w[st[g][0]]);
			printf("%d\n",ans);
		}
	}

}


#include<cstdlib>
#include<cstdio>
#include<queue>
using namespace std;
const int N=200010;
int n,m,Q,cnt1,cnt,mcnt,w[N<<1],q[N],top,dfncnt,low[N],dfn[N],id[N<<1],id_1[N<<1],idcnt,a[N<<1],dep[N<<1],st[N<<1][20],size[N<<1],son[N<<1],tp[N<<1],segcnt;
char inc[10];
struct node{int v;node *next;}pool[N<<3],*h1[N],*h[N<<1];
void add1(int u,int v)
{
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h1[u];h1[u]=p;
	q->v=u;q->next=h1[v];h1[v]=q;
}
void add(int u,int v)
{
//	printf("add %d %d\n",u,v);
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h[u];h[u]=p;
	q->v=u;q->next=h[v];h[v]=q;
}
struct heap
{
	priority_queue<int,vector<int>,greater<int> >pq,dl;
	void push(int x){pq.push(x);}
	void del(int x)
	{
		dl.push(x);
		while(!pq.empty()&&pq.top()==dl.top()) pq.pop(),dl.pop();
	}
	int top(){return pq.top();}
}hp[N<<1];
void tarjan(int u)
{
	low[u]=dfn[u]=++dfncnt;
	int topu=top;
	for(node *t=h1[u];t;t=t->next)
		if(dfn[t->v]==0)
		{
			q[++top]=t->v;
			tarjan(t->v);
			low[u]=min(low[u],low[t->v]);
			if(low[t->v]>=dfn[u])
			{
				int p=++mcnt;
				for(int i=topu;i<=top;i++) add(p,q[i]),hp[p].push(w[q[i]]);//,vt[q[i]][++vt[q[i]][0]]=p;
				//w[p]=hp[p].top();
				top=topu;
			}
		}
		else low[u]=min(low[u],dfn[t->v]);
}
int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int d=dep[x]-dep[y],k=0;d;d>>=1,k++)
		if(d&1) x=st[x][k];
	if(x==y) return x;
	for(int k=18;k>=0;k--)
		if(st[x][k]^st[y][k])
			x=st[x][k],y=st[y][k];
	return st[x][0];
}
void dfs1(int u,int fa)
{
	st[u][0]=fa;
	dep[u]=dep[fa]+1;
	size[u]=1;
	for(node *t=h[u];t;t=t->next)
		if(t->v^fa)
			dfs1(t->v,u),
			size[u]+=size[t->v],
			son[u]=size[t->v]>size[son[u]]?t->v:son[u];
}
void dfs2(int u,int fa)
{
	a[id[u]=++idcnt]=w[u];
	id_1[idcnt]=u;
	if(son[u]) tp[son[u]]=tp[u],dfs2(son[u],u);
	for(node *t=h[u];t;t=t->next)
		if((t->v^son[u])&&(t->v^fa))
			tp[t->v]=t->v,dfs2(t->v,u);
}
struct seg{int mn,l,r;seg *ls,*rs;}segpool[N<<2],*root;
seg* build(int l,int r)
{
	seg *t=&segpool[++segcnt];
	t->l=l;t->r=r;
	if(l==r){t->mn=w[id_1[l]];return t;}
	int mid=l+r>>1;
	t->ls=build(l,mid);
	t->rs=build(mid+1,r);
	t->mn=min(t->ls->mn,t->rs->mn);
	return t;
}
void chg(seg *t,int pos,int x)
{
	if(t->l==t->r){t->mn=x;return;}
	int mid=t->l+t->r>>1;
	if(pos<=mid) chg(t->ls,pos,x);
	else chg(t->rs,pos,x);
	t->mn=min(t->ls->mn,t->rs->mn);
}
int qry(seg *t,int l,int r)
{
	//if(t==root) printf("qry %d %d\n",l,r);
	if(t->l>=l&&t->r<=r) return t->mn;
	int ans=2147483600,mid=t->l+t->r>>1;
	if(l<=mid) ans=min(ans,qry(t->ls,l,r));
	if(r>mid) ans=min(ans,qry(t->rs,l,r));
	//printf("qry       %d %d   %d %d  = %d\n",t->l,t->r,l,r,ans);
	return ans;
}

int ask(int x,int g)
{
	int ans=2147483600;
	while(tp[x]^tp[g])
		ans=min(ans,qry(root,id[tp[x]],id[x])),
		x=st[tp[x]][0];
	ans=min(ans,qry(root,id[g],id[x]));
	return ans;
}

int main()
{
	scanf("%d%d%d",&n,&m,&Q);
	mcnt=n;
	for(int i=1;i<=n;i++) scanf("%d",&w[i]);//,vt[i].push_back(0);
	for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),add1(x,y);
	q[++top]=1;tarjan(1);
	/*for(int i=1;i<=n;i++)
	{
		printf("vt[%d]  ( %d ): ",i,w[i]);
		for(int j=1;j<=vt[i][0];j++) printf("%d ",vt[i][j]);
		printf("\n");
	}
	for(int i=1;i<=mcnt;i++) printf("%d %d  \n",i,w[i]);
	*/
	dfs1(1,0);//dep,fa,son
	tp[1]=1;dfs2(1,0);//tp,id
	for(int k=1;k<19;k++)
		for(int i=1;i<=mcnt;i++)
			st[i][k]=st[st[i][k-1]][k-1];

	for(int i=n+1;i<=mcnt;i++) hp[i].del(w[st[i][0]]),w[i]=hp[i].top();
	//for(int i=1;i<=mcnt;i++) printf("== %d %d %d  %d\n",i,w[i],tp[i],id[i]);
	root=build(1,mcnt);
	for(int i=1,x,y;i<=Q;i++)
	{
		scanf("%s%d%d",inc+1,&x,&y);
		if(inc[1]=='C')
		{
			if(st[x][0]>n)
			{
				hp[st[x][0]].del(w[x]);
				hp[st[x][0]].push(y);
				chg(root,id[st[x][0]],hp[st[x][0]].top());
			}
			chg(root,id[x],y);
			w[x]=y;
		}
		else
		{
			int g=lca(x,y),ans;
			ans=min(ask(y,g),ask(x,g));
			//printf("g= %d  ans=%d\n",g,ans);
			if(g>n) ans=min(ans,w[st[g][0]]);
			printf("%d\n",ans);
		}
	}

}


#include<cstdlib>
#include<cstdio>
#include<queue>
using namespace std;
const int N=100010;
int n,m,Q,cnt1,cnt,mcnt,w[N<<1],q[N],top,dfncnt,low[N],dfn[N],id[N<<1],id_1[N<<1],idcnt,dep[N<<1],f[N<<1],size[N<<1],son[N<<1],tp[N<<1],segcnt,g0;
char inc[10];
struct node{int v;node *next;}pool[N<<3],*h1[N],*h[N<<1];
void add1(int u,int v)
{
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h1[u];h1[u]=p;
	q->v=u;q->next=h1[v];h1[v]=q;
}
void add(int u,int v)
{
	node *p=&pool[++cnt],*q=&pool[++cnt];
	p->v=v;p->next=h[u];h[u]=p;
	q->v=u;q->next=h[v];h[v]=q;
}
struct heap
{
	priority_queue<int,vector<int>,greater<int> >pq,dl;
	void push(int x){pq.push(x);}
	void del(int x)	{dl.push(x);}
	int top(){	while(!pq.empty()&&!dl.empty()&&pq.top()==dl.top()) pq.pop(),dl.pop(); return pq.top(); }
}hp[N<<1];
void tarjan(int u)
{
	low[u]=dfn[u]=++dfncnt;
	for(node *t=h1[u];t;t=t->next)
		if(dfn[t->v]==0)
		{
			int topu=top;
			q[++top]=t->v;
			tarjan(t->v);
			low[u]=min(low[u],low[t->v]);
			if(low[t->v]>=dfn[u])
			{
				int p=++mcnt;
				for(int i=topu+1;i<=top;i++) add(p,q[i]);//,hp[p].push(w[q[i]]);
				add(p,u);//hp[p].push(w[u]);
				top=topu;
			}
		}
		else low[u]=min(low[u],dfn[t->v]);
}

void dfs1(int u,int fa)
{
	f[u]=fa;
	dep[u]=dep[fa]+1;
	size[u]=1;
	for(node *t=h[u];t;t=t->next)
		if(t->v^fa)
			dfs1(t->v,u),
			size[u]+=size[t->v],
			son[u]=size[t->v]>size[son[u]]?t->v:son[u];
}
void dfs2(int u,int fa)
{
	id_1[id[u]=++idcnt]=u;
	if(son[u]) tp[son[u]]=tp[u],dfs2(son[u],u);
	for(node *t=h[u];t;t=t->next)
		if((t->v^son[u])&&(t->v^fa))
			tp[t->v]=t->v,dfs2(t->v,u);
}
struct seg{int mn,l,r;seg *ls,*rs;}segpool[N<<2],*root;
seg* build(int l,int r)
{
	seg *t=&segpool[++segcnt];
	t->l=l;t->r=r;
	if(l==r){t->mn=w[id_1[l]];return t;}
	int mid=l+r>>1;
	t->ls=build(l,mid);
	t->rs=build(mid+1,r);
	t->mn=min(t->ls->mn,t->rs->mn);
	return t;
}
void chg(seg *t,int pos,int x)
{
	if(t->l==t->r){t->mn=x;return;}
	int mid=t->l+t->r>>1;
	if(pos<=mid) chg(t->ls,pos,x);
	else chg(t->rs,pos,x);
	t->mn=min(t->ls->mn,t->rs->mn);
}
int qry(seg *t,int l,int r)
{
	if(t->l>=l&&t->r<=r) return t->mn;
	int ans=2147483600,mid=t->l+t->r>>1;
	if(l<=mid) ans=min(ans,qry(t->ls,l,r));
	if(r>mid) ans=min(ans,qry(t->rs,l,r));
	return ans;
}

int ask(int x,int y)
{
	int ans=2147483600;
	while(tp[x]^tp[y])
	{
		if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
		ans=min(ans,qry(root,id[tp[x]],id[x])),
		x=f[tp[x]];
	}
	if(dep[x]<dep[y]) swap(x,y);
	ans=min(ans,qry(root,id[y],id[x]));
	g0=y;
	return ans;
}
int rd()
{
	char cx=getchar();int ret=0;
	while(cx<'0'||cx>'9') cx=getchar();
	while(cx>='0'&&cx<='9') ret=ret*10+cx-'0',cx=getchar();
	return ret;
}

int main()
{
	scanf("%d%d%d",&n,&m,&Q);
	mcnt=n;
	for(int i=1;i<=n;i++) w[i]=rd();
	for(int i=1,x,y;i<=m;i++) x=rd(),y=rd(),add1(x,y);
	q[++top]=1;tarjan(1);
	dfs1(1,0);//dep,fa,son
	tp[1]=1;dfs2(1,0);//tp,id
	for(int i=1;i<=n;i++) if(f[i]>n) {hp[f[i]].push(w[i]);}
	for(int i=n+1;i<=mcnt;i++) { w[i]=hp[i].top();}

	root=build(1,mcnt);
	for(int i=1,x,y;i<=Q;i++)
	{
		scanf("%s%d%d",inc+1,&x,&y);
		if(inc[1]=='C')
		{
			if(f[x]>n)
			{
				hp[f[x]].del(w[x]);
				hp[f[x]].push(y);
				chg(root,id[f[x]],hp[f[x]].top());
			}
			chg(root,id[x],y);
			w[x]=y;
		}
		else
		{
			int ans=ask(x,y);
			if(g0>n) ans=min(ans,w[f[g0]]);
			printf("%d\n",ans);
		}
	}
}


#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std; using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast") //#pragma GCC optimize "unroll-loops" //#pragma GCC optimize "prefetch-loop-arrays" //#pragma GCC target "sse,sse2,sse3,sse4,abm,avx,aes,sse4a,sse4.1,sse4.2,mmx,popcnt,tune=native"
#define foru(i,a,b) for(int i=(a);i<(b);i++)
#define ford(i,a,b) for(int i=(a);i>=(b);i--)
#define fori(a,b) foru(i,a,b)
#define forj(a,b) foru(j,a,b)
#define fork(a,b) foru(k,a,b)
#define seto(x,i) memset(x,i,sizeof x)
#define pf first
#define ps second
#define pb push_back
#define eb emplace_back
#define popcount __builtin_popcount
#define popcountll __builtin_popcountll
#define clz __builtin_clz
#define clzll __builtin_clzll
#define ctz __builtin_ctz
#define ctzll __builtin_ctzll
#define P2(x) (1LL<<(x))
#define sz(x) (int)x.size()
#define all(x) begin(x),end(x)
#if __SIZEOF_INT128__
    typedef __int128_t i128; typedef __uint128_t ui128;
#else
    typedef long long i128; typedef unsigned long long ui128;
#endif
typedef int64_t ll;  typedef uint64_t ull; typedef int8_t byte; typedef long double lld;
typedef pair<int,int> pii; typedef pair<ll,ll> pll; typedef pair<lld,lld> pdd;
template<typename T1,typename T2> using ordered_map=tree<T1,T2,less<T1>,rb_tree_tag,tree_order_statistics_node_update>;
template<typename T1> using ordered_set=ordered_map<T1,null_type>;
const int inf=0x3f3f3f3f,MOD=1e9+7; const ll INF=0x3f3f3f3f3f3f3f3f; const lld PI=acos((lld)-1);
ll gcd(ll a, ll b){return b?gcd(b,a%b):a;}
ll fpow(ll a,ll b){if(!b) return 1; ll t=fpow(a,b/2); if(b&1) return t*t%MOD*a%MOD; return t*t%MOD;}
const ll SEED=chrono::duration_cast<chrono::nanoseconds>(chrono::high_resolution_clock::now().time_since_epoch()).count();
mt19937 randgen(SEED); int randint(int a, int b){return uniform_int_distribution<int>(a,b)(randgen);} ll randll(ll a, ll b){return uniform_int_distribution<ll>(a,b)(randgen);}
template<class T1,class T2>constexpr const auto _min(const T1&x,const T2&y){return x<y?x:y;} template<class T,class...Ts>constexpr auto _min(const T&x,const Ts&...xs){return _min(x,_min(xs...));}
template<class T1,class T2>constexpr const auto _max(const T1&x,const T2&y){return x>y?x:y;} template<class T,class...Ts>constexpr auto _max(const T&x,const Ts&...xs){return _max(x,_max(xs...));}
#define min(...) _min(__VA_ARGS__)
#define max(...) _max(__VA_ARGS__)
struct chash{
    static ll splitmix64(ll x){x+=0x9e3779b97f4a7c15; x=(x^(x>>30))*0xbf58476d1ce4e5b9; x=(x^(x>>27))*0x94d049bb133111eb; return x^(x>>31);}
    template<class T> size_t operator()(const T &x) const{return splitmix64(hash<T>()(x)+SEED);}
    template<class T1,class T2> size_t operator()(const pair<T1,T2>&x)const{return 31*operator()(x.first)+operator()(x.second);}
};
#define nl "\n"

const int N=P2(18),M=MOD;
int n,m,q,n2,a,b,val[N],dfn[N],low[N],sz[N],par[N],top[N],dep[N];
vector<int> gr[N],gr2[N];
stack<int> scc;
bitset<N> art;
char ch;
struct SegTree{
    int seg[2*N];
    SegTree(){seto(seg,inf);}
    void pull(int x){seg[x]=min(seg[2*x],seg[2*x+1]);}
    void upd(int x,int v){
        seg[x+=N]=v;
        for(x/=2;x;x/=2) pull(x);
    }
    int query(int l,int r){
        int ret=inf;
        for(l+=N,r+=N+1;l<r;l/=2,r/=2){
            if(l&1) ret=min(ret,seg[l++]);
            if(r&1) ret=min(seg[--r],ret);
        }
        return ret;
    }
} st;
void tarjan(int v,int p=-1){
    dfn[v]=low[v]=a++; scc.push(v);
    for(auto i:gr2[v]) if(i!=p){
        if(dfn[i]) low[v]=min(low[v],dfn[i]);
        else{
            tarjan(i,v);
            if(low[i]>=dfn[v]){
                n2++; val[n2]=inf; art[v]=1;
                for(;scc.top()!=v&&low[scc.top()]>=dfn[v];scc.pop()){
                    int x=scc.top(); gr[x].pb(n2); gr[n2].pb(x); val[n2]=min(val[n2],val[x]);
                }
                if(low[i]==dfn[v]){
                    gr[n2].pb(v); gr[v].pb(n2);
                }
                else{
                    gr[i].pb(v); gr[v].pb(i);
                }
            }
            low[v]=min(low[v],low[i]);
        }
    }
}
void szdfs(int v,int p=-1){
    sz[v]=1;
    for(auto& i:gr[v]) if(i!=p){
        szdfs(i,v); sz[v]+=sz[i];
        if(gr[v][0]==p||sz[i]>sz[gr[v][0]]) swap(i,gr[v][0]);
    }
}
void hlddfs(int v,int p=0){
    dfn[v]=++a; par[v]=p; st.upd(dfn[v],val[v]);
    for(auto i:gr[v]) if(i!=p){
        top[i]=i==gr[v][0]? top[v]: i;
        hlddfs(i,v);
    }
}
int query(int u,int v){
    int ret=inf;
    while(top[u]!=top[v]){
        if(dfn[top[u]]>dfn[top[v]]) swap(u,v);
        ret=min(ret,st.query(dfn[top[v]],dfn[v]));
        v=par[top[v]];
    }
    if(dfn[u]>dfn[v]) swap(u,v);
    ret=min(ret,st.query(dfn[u],dfn[v]));
    if(art[par[u]]) ret=min(ret,st.query(dfn[par[u]],dfn[par[u]]));
    return ret;
}

int main(){
    ios_base::sync_with_stdio(0); cin.tie(0);
    //freopen("", "r", stdin); //freopen("", "w", stdout);
    cin>>n>>m>>q;
    fori(1,n+1) cin>>val[i];
    fori(0,m){
        cin>>a>>b; gr2[a].pb(b); gr2[b].pb(a);
    }
    gr2[0].pb(1); n2=n; tarjan(0); szdfs(1); a=0; top[1]=1; hlddfs(1);
    while(q--){
        cin>>ch>>a>>b;
        if(ch=='A') cout<<query(a,b)<<nl;
        else if(ch=='C'){
            if(art[a]) st.upd(dfn[a],b);
            if(!art[par[a]]) st.upd(dfn[par[a]],b);
        }
    }
    return 0;
}
/**

*/