#include <iostream>
#include <cstdlib>
#include <cstdio>

using namespace std;

const int MAX_N = 1 << 11;
const int INF = 1000000005;

int n, q;
int a[MAX_N][MAX_N];

struct Segment {
    int tree[2 * MAX_N];

    Segment() {
        for (int i = 0; i < 2 * MAX_N; ++i)
            tree[i] = INF;
    }

    void update(int x, int by, int force = 0) {
        int pos = x + MAX_N - 1;
        if (force) tree[pos] = by;
        else tree[pos] = min(tree[pos], by);
        while (pos > 0) {
            pos = (pos - 1) / 2;
            tree[pos] = min(tree[pos * 2 + 1], tree[pos * 2 + 2]);
        }
    }

    int get(int node, int low, int high, int nlow, int nhigh) {
        if (nlow > high || nhigh < low) return INF;
        if (low >= nlow && high <= nhigh) return tree[node];
        int mid = (low + high) / 2;
        int res = INF;
        res = min(res, get(node * 2 + 1, low, mid, nlow, nhigh));
        res = min(res, get(node * 2 + 2, mid + 1, high, nlow, nhigh));
        return res;
    }
} row, col, rpc[2 * MAX_N], rmc[2 * MAX_N];

int main() {
    freopen("pentranje.in", "r", stdin);
    freopen("pentranje.out", "w", stdout);
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j) {
            scanf("%d", &a[i][j]);
            row.update(i + j, a[i][j]);
            col.update(j - i + MAX_N / 2, a[i][j]);
            rpc[i + j].update(j - i + MAX_N / 2, a[i][j]);
            rmc[j - i + MAX_N / 2].update(i + j, a[i][j]);
        }
    scanf("%d", &q);
    for (int query = 0; query < q; ++query) {
        int type;
        scanf("%d", &type);
        if (type == 1) {
            int r, c;
            scanf("%d%d", &r, &c);
            --r;
            --c;
            int low = 0;
            int high = 2 * n;
            while (low < high) {
                int mid = (low + high + 1) / 2;
                int r1 = row.get(0, 0, MAX_N - 1, 0, r + c - mid);
                int r2 = row.get(0, 0, MAX_N - 1, r + c + mid, MAX_N - 1);
                int c1 = col.get(0, 0, MAX_N - 1, 0, c - r + MAX_N / 2 - mid);
                int c2 = col.get(0, 0, MAX_N - 1, c - r + MAX_N / 2 + mid, MAX_N - 1);
                int maxNum = min(r1, min(r2, min(c1, c2)));
                if (maxNum < a[r][c]) low = mid;
                else high = mid - 1;
            }
            if (low == 0) printf("-1\n");
            else printf("%d\n", low);
        } else {
            int r, c, v;
            scanf("%d%d%d", &r, &c, &v);
            --r;
            --c;
            if (v != a[r][c]) {
                rpc[r + c].update(c - r + MAX_N / 2, v, 1);
                rmc[c - r + MAX_N / 2].update(r + c, v, 1);
                row.update(r + c, rpc[r + c].tree[0], 1);
                col.update(c - r + MAX_N / 2, rmc[c - r + MAX_N / 2].tree[0], 1);
                a[r][c] = v;
            }
        }
    }
    return 0;
}
