The Free Meteor Association (FMA) has got a problem: as meteors are moving, the Universal Cosmic Descriptive Humorous Program (UCDHP) needs to add a special module that would analyze this movement. 

UCDHP stores some secret information about meteors as an n × m table with integers in its cells. The order of meteors in the Universe is changing. That's why the main UCDHP module receives the following queries:

  * The query to swap two table rows; 
  * The query to swap two table columns; 
  * The query to obtain a secret number in a particular table cell. 



As the main UCDHP module is critical, writing the functional of working with the table has been commissioned to you.

Input

The first line contains three space-separated integers n, m and k (1 ≤ n, m ≤ 1000, 1 ≤ k ≤ 500000) — the number of table columns and rows and the number of queries, correspondingly.

Next n lines contain m space-separated numbers each — the initial state of the table. Each number p in the table is an integer and satisfies the inequality 0 ≤ p ≤ 106.

Next k lines contain queries in the format "si xi yi", where si is one of the characters "с", "r" or "g", and xi, yi are two integers.

  * If si = "c", then the current query is the query to swap columns with indexes xi and yi (1 ≤ x, y ≤ m, x ≠ y); 
  * If si = "r", then the current query is the query to swap rows with indexes xi and yi (1 ≤ x, y ≤ n, x ≠ y); 
  * If si = "g", then the current query is the query to obtain the number that located in the xi-th row and in the yi-th column (1 ≤ x ≤ n, 1 ≤ y ≤ m). 



The table rows are considered to be indexed from top to bottom from 1 to n, and the table columns — from left to right from 1 to m.

Output

For each query to obtain a number (si = "g") print the required number. Print the answers to the queries in the order of the queries in the input.

Examples

Input

3 3 5
1 2 3
4 5 6
7 8 9
g 3 2
r 3 2
c 2 3
g 2 2
g 3 2


Output

8
9
6


Input

2 3 3
1 2 4
3 1 5
c 2 1
r 1 2
g 1 3


Output

5

Note

Let's see how the table changes in the second test case.

After the first operation is fulfilled, the table looks like that:

2 1 4

1 3 5

After the second operation is fulfilled, the table looks like that:

1 3 5

2 1 4

So the answer to the third query (the number located in the first row and in the third column) will be 5.
import java.util.*;
import java.lang.*;
import java.io.*;
import java.math.*;

public class Codeforces {

    static double Phi = (1 + Math.sqrt(5)) / 2.0;
    static int MAX = -1 >>> 1;
    static long MODL = 1_000_000_007L;
    static int MOD = 1_000_000_007;
    static void no() {println("NO");}
    static void yes() {println("YES");}

    static void main2() throws Exception {
        int n = ni();
        int m = ni();
        int k = ni();

        int[] realRow = new int[n];
        int[] realCol = new int[m];

        int[][] data = new int[n][m];
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < m; j++) {
                data[i][j] = ni();
            }
        } 
        
        for(int i = 0; i < n; i++) {
            realRow[i] = i;
        }
        for(int i = 0; i < m; i++) {
            realCol[i] = i;
        }

        while(k-- > 0) {
            String[] query = line().split("\\s");
            char c = query[0].charAt(0);
            int x = Integer.parseInt(query[1]) - 1;
            int y = Integer.parseInt(query[2]) - 1;
            switch(c) {
                case 'c': {
                    //swap col x and y
                    int temp = realCol[x];
                    realCol[x] = realCol[y];
                    realCol[y] = temp;
                    break;
                }
                case 'r': {
                    //swap col x and y
                    int temp = realRow[x];
                    realRow[x] = realRow[y];
                    realRow[y] = temp;
                    break;
                }
                case 'g': {
                    int row = realRow[x];
                    int col = realCol[y];
                    println(data[row][col]);
                    break;
                }
            }
            // println(Arrays.toString(realRow));
            // println(Arrays.toString(realCol));
            // println("-");
        }

    }
    //            /$$
    //           | $$
    //   /$$$$$$$| $$  /$$$$$$   /$$$$$$$ /$$$$$$$  /$$$$$$   /$$$$$$$
    //  /$$_____/| $$ |____  $$ /$$_____//$$_____/ /$$__  $$ /$$_____/
    // | $$      | $$  /$$$$$$$|  $$$$$$|  $$$$$$ | $$$$$$$$|  $$$$$$
    // | $$      | $$ /$$__  $$ \____  $$\____  $$| $$_____/ \____  $$
    // |  $$$$$$$| $$|  $$$$$$$ /$$$$$$$//$$$$$$$/|  $$$$$$$ /$$$$$$$/
    //  \_______/|__/ \_______/|_______/|_______/  \_______/|_______/

    static class Pair <L, R> {
        L first;
        R second;

        Pair(L first, R second) {
            this.first = first;
            this.second = second;
        }

        Pair(Pair<L, R> p) {
            this.first = p.first;
            this.second = p.second;
        }

        public boolean equals(Object p2) {
            if (p2 instanceof Pair) {
                return ((Pair) p2).first.equals(first) && ((Pair) p2).second.equals(second);
            }
            return false;
        }

        public String toString() {
            return "(first=" + first.toString() + ",second=" + second.toString() + ")";
        }
    }

    static class DisjointSet {
        int[] arr;
        int[] size;
        boolean enableSize = true;

        DisjointSet(int n) {
            arr = new int[n + 1];
            this.enableSize = enableSize;
            if (this.enableSize) size = new int[n + 1];
            makeSet();
        }

        void makeSet() {
            for (int i = 1; i < arr.length; i++) {
                arr[i] = i;
                if (enableSize) size[i] = 1;
            }
        }

        void union(int i, int j) {
            i = find(i);
            j = find(j);

            if (i == j)
                return;
            arr[j] = arr[i];
            if (enableSize) {
                size[i] += size[j];
                size[j] = size[i];
            }
        }

        int find(int i) {
            if (i == arr[i]) return i;
            return arr[i] = find(arr[i]);
        }

        int getSize(int i) {
            if (enableSize) return size[find(i)];
            return 0;
        }

        public String toString() {
            return Arrays.toString(arr);
        }
    }

    //              /$$     /$$ /$$
    //             | $$    |__/| $$
    //  /$$   /$$ /$$$$$$   /$$| $$  /$$$$$$$
    // | $$  | $$|_  $$_/  | $$| $$ /$$_____/
    // | $$  | $$  | $$    | $$| $$|  $$$$$$
    // | $$  | $$  | $$ /$$| $$| $$ \____  $$
    // |  $$$$$$/  |  $$$$/| $$| $$ /$$$$$$$/
    //  \______/    \___/  |__/|__/|_______/


    static int diff(int a, int b) {
        return abs(a - b);
    }

    static long diff(long a, long b) {
        return abs(a - b);
    }

    static boolean isSqrt(double a) {
        double sr = Math.sqrt(a);
        return ((sr - Math.floor(sr)) == 0);
    }

    static long abs(long a) {
        return Math.abs(a);
    }

    static int abs(int a) {
        return Math.abs(a);
    }

    static int min(int ... arr) {
        int min = Integer.MAX_VALUE;
        for (int var : arr)
            min = Math.min(min, var);
        return min;
    }

    static long min(long ... arr) {
        long min = Long.MAX_VALUE;
        for (long var : arr)
            min = Math.min(min, var);
        return min;
    }

    static long max(long ... arr) {
        long max = Long.MIN_VALUE;
        for (long var : arr)
            max = Math.max(max, var);
        return max;
    }

    static int max(int... arr) {
        int max = Integer.MIN_VALUE;
        for (int var : arr)
            max = Math.max(max, var);
        return max;
    }

    static long modInverse(long a) {
        long[] g = gcde(a, MODL);
        long x = g[1], y = g[2];
        if (g[0] != 1)
            return 0;
        else {
            // m is added to handle negative x
            return (g[1] % MODL + MODL) % MODL;
        }
    }

    static long gcd(long a, long b) {
        if (b == 0)
            return a;
        return gcd(b, a % b);
    }

    static long[] gcde(long a, long b) {
        // Base Case
        if (a == 0) {
            return new long[] {b, 0, 1};
        }

        long[] gcd = gcde(b % a, a);
        long x1 = gcd[1], y1 = gcd[2]; // To store results of recursive call

        // Update x and y using results of recursive
        // call
        gcd[1] = y1 - (b / a) * x1;
        gcd[2] = x1;

        return gcd;
    }

    // ____________________________________________________________________________
    //|                                                                            |
    //|  /$$$$$$  /$$$$$$         /$$$$$$   /$$                /$$$$$$   /$$$$$$   |
    //| |_  $$_/ /$$__  $$       /$$__  $$ | $$               /$$__  $$ /$$__  $$  |
    //|   | $$  | $$  \ $$      | $$  \__//$$$$$$   /$$   /$$| $$  \__/| $$  \__/  |
    //|   | $$  | $$  | $$      |  $$$$$$|_  $$_/  | $$  | $$| $$$$    | $$$$      |
    //|   | $$  | $$  | $$       \____  $$ | $$    | $$  | $$| $$_/    | $$_/      |
    //|   | $$  | $$  | $$       /$$  \ $$ | $$ /$$| $$  | $$| $$      | $$        |
    //|  /$$$$$$|  $$$$$$/      |  $$$$$$/ |  $$$$/|  $$$$$$/| $$      | $$        |
    //| |______/ \______/        \______/   \___/   \______/ |__/      |__/        |
    //|____________________________________________________________________________|



    private static byte[] scannerByteBuffer = new byte[1024]; // Buffer of Bytes
    private static int scannerIndex;
    private static InputStream scannerIn;
    private static int scannerTotal;
    private static BufferedWriter printerBW;
    private static boolean DEBUG = false;

    private static int next() throws IOException { // Scan method used to scan buf
        if (scannerTotal < 0)
            throw new InputMismatchException();
        if (scannerIndex >= scannerTotal) {
            scannerIndex = 0;
            scannerTotal = scannerIn.read(scannerByteBuffer);
            if (scannerTotal <= 0)
                return -1;
        }
        return scannerByteBuffer[scannerIndex++];
    }

    static int ni() throws IOException {
        int integer = 0;
        int n = next();
        while (isWhiteSpace(n)) // Removing startPointing whitespaces
            n = next();
        int neg = 1;
        if (n == '-') { // If Negative Sign encounters
            neg = -1;
            n = next();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = next();
            } else
                throw new InputMismatchException();
        }
        return neg * integer;
    }

    static long nl() throws IOException {
        long integer = 0;
        int n = next();
        while (isWhiteSpace(n)) // Removing startPointing whitespaces
            n = next();
        int neg = 1;
        if (n == '-') { // If Negative Sign encounters
            neg = -1;
            n = next();
        }
        while (!isWhiteSpace(n)) {
            if (n >= '0' && n <= '9') {
                integer *= 10;
                integer += n - '0';
                n = next();
            } else
                throw new InputMismatchException();
        }
        return neg * integer;
    }

    static String line() throws IOException {
        StringBuilder sb = new StringBuilder();
        int n = next();
        while (isWhiteSpace(n))
            n = next();
        while (!isNewLine(n)) {
            sb.append((char) n);
            n = next();
        }
        return sb.toString();
    }

    private static boolean isNewLine(int n) {
        return n == '\n' || n == '\r' || n == -1;
    }

    private static boolean isWhiteSpace(int n) {
        return n == ' ' || isNewLine(n) || n == '\t';
    }

    static int[] nia(int n) throws Exception {
        if (n < 0)
            throw new Exception("Array size should be non negative");
        int[] array = new int[n];
        for (int i = 0; i < n; i++)
            array[i] = ni();
        return array;
    }

    static int[][] n2dia(int r, int c) throws Exception {
        if (r < 0 || c < 0)
            throw new Exception("Array size should be non negative");
        int[][] array = new int[r][c];
        for (int i = 0; i < r; i++)
            array[i] = nia(c);
        return array;
    }

    static long[] nla(int n) throws Exception {
        if (n < 0)
            throw new Exception("Array size should be non negative");
        long[] array = new long[n];
        for (int i = 0; i < n; i++)
            array[i] = nl();
        return array;
    }

    static float[] nfa(int n) throws Exception {
        if (n < 0)
            throw new Exception("Array size should be non negative");
        float[] array = new float[n];
        for (int i = 0; i < n; i++)
            array[i] = nl();
        return array;
    }

    static double[] nda(int n) throws Exception {
        if (n < 0)
            throw new Exception("Array size should be non negative");
        double[] array = new double[n];
        for (int i = 0; i < n; i++)
            array[i] = nl();
        return array;
    }

    static <T> void print(T ... str) {
        try {
            for (T ele : str)
                printerBW.append(ele.toString());
            if (DEBUG)
                flush();
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }

    static <T> void println(T ... str) {
        if (str.length == 0) {
            print('\n');
            return;
        }
        for (T ele : str)
            print(ele, '\n');
    }

    static void flush() throws IOException {
        printerBW.flush();
    }

    static void close() {
        try {
            printerBW.close();
        } catch (IOException e) {
            System.out.println(e.toString());
        }
    }

    public static void main(String[] args) throws Exception {
        long startPointTime = System.currentTimeMillis();
        scannerIn = System.in;
        printerBW = new BufferedWriter(new OutputStreamWriter(System.out));
        if (args.length > 0 && args[0].equalsIgnoreCase("debug")
                || args.length > 1 && args[1].equalsIgnoreCase("debug"))
            DEBUG = true;

        main2();
        long endTime = System.currentTimeMillis();
        float totalProgramTime = endTime - startPointTime;
        if (args.length > 0 && args[0].equalsIgnoreCase("time") || args.length > 1 && args[1].equalsIgnoreCase("time"))
            print("Execution time is " + totalProgramTime + " (" + (totalProgramTime / 1000) + "s)");
        close();
    }
}
