/*
    2度あることはn回ある(帰納法)
 */

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

#define INF 0xffffffff

int r;
int c;
int q;
int sizex;
int sizey;


class Seg2d {
public:
    vector<unsigned int> grid;
    int width;
    int height;

    inline int get_idx(int watchl, int watchr, int watchu, int watchd) {
        int hori = watchr - watchl;
        int vert = watchd - watchu;
        if (hori == 0 || vert == 0) return -1;
        return (watchu/vert) * width/hori + watchl/hori;
    }

    Seg2d (int sizex, int sizey) : width(sizex), height(sizey) {
        long long int a = min(width, height);
        long long int b = max(width, height);
        long long int size = (4*a*a-1)/3 + 2*a*(b-a);

        grid.resize(size, INF);
    }
    ~Seg2d() {grid.clear();}

    void _update(int wishl, int wishr, int wishu, int wishd, int base, int watchl, int watchr, int watchu, int watchd, unsigned int x) {
        int midx, midy;
        unsigned int idx, idx1, idx2, idx3, idx4;
        int hori = watchr - watchl;
        int vert = watchd - watchu;
        int newbase;

        if (hori == 0 || vert == 0) return;
        if (wishr <= watchl || watchr <= wishl || wishd <= watchu || watchd <= wishu) return;
        if (wishl <= watchl && watchr <= wishr && wishu <= watchu && watchd <= wishd) {
            grid[base+get_idx(watchl, watchr, watchu, watchd)] = x;
            return;
        }

        midx = (watchl+watchr)/2;
        midy = (watchu+watchd)/2;
        newbase = base + width/hori * height/vert;
        _update(wishl, wishr, wishu, wishd, newbase, watchl, midx, watchu, midy, x);
        _update(wishl, wishr, wishu, wishd, newbase, midx, watchr, watchu, midy, x);
        _update(wishl, wishr, wishu, wishd, newbase, watchl, midx, midy, watchd, x);
        _update(wishl, wishr, wishu, wishd, newbase, midx, watchr, midy, watchd, x);
        idx  = get_idx(watchl, watchr, watchu, watchd);
        idx1 = get_idx(watchl, midx, watchu, midy);
        idx2 = get_idx(midx, watchr, watchu, midy);
        idx3 = get_idx(watchl, midx, midy, watchd);
        idx4 = get_idx(midx, watchr, midy, watchd);
        if (idx != -1) {
            grid[base+idx] = INF;
            if (idx1 != -1) grid[base+idx] = min(grid[base+idx], grid[newbase+idx1]);
            if (idx2 != -1) grid[base+idx] = min(grid[base+idx], grid[newbase+idx2]);
            if (idx3 != -1) grid[base+idx] = min(grid[base+idx], grid[newbase+idx3]);
            if (idx4 != -1) grid[base+idx] = min(grid[base+idx], grid[newbase+idx4]);
        }
    }

    void update(int x, int y, unsigned int t) {
        _update(x, x+1, y, y+1, 0, 0, width, 0, height, t);
    }

    unsigned int _getMin(int wishl, int wishr, int wishu, int wishd, int base, int watchl, int watchr, int watchu, int watchd) {
        int midx, midy;
        unsigned int val1, val2, val3, val4;
        int hori = watchr - watchl;
        int vert = watchd - watchu;
        int newbase;

        if (hori == 0 || vert == 0) return INF;
        if (wishr <= watchl || watchr <= wishl || wishd <= watchu || watchd <= wishu) return INF;
        if (wishl <= watchl && watchr <= wishr && wishu <= watchu && watchd <= wishd) {
            return grid[base+get_idx(watchl, watchr, watchu, watchd)];
        }

        midx = (watchl+watchr)/2;
        midy = (watchu+watchd)/2;
        newbase = base + width/hori * height/vert;
        val1 = _getMin(wishl, wishr, wishu, wishd, newbase, watchl, midx, watchu, midy);
        val2 = _getMin(wishl, wishr, wishu, wishd, newbase, midx, watchr, watchu, midy);
        val3 = _getMin(wishl, wishr, wishu, wishd, newbase, watchl, midx, midy, watchd);
        val4 = _getMin(wishl, wishr, wishu, wishd, newbase, midx, watchr, midy, watchd);
        return min(min(val1, val2), min(val3, val4));
    }

    unsigned int getMin(int x1, int x2, int y1, int y2) { // [x1, x2) [y1, y2)
        return _getMin(x1, x2, y1, y2, 0, 0, width, 0, height);
    }
};

int main() {
    while (1) {
        scanf("%d %d %d", &r, &c, &q);
        if (r == 0 && c == 0 && q == 0) return 0;

        sizex = 1;
        while (sizex < c) sizex *= 2;
        sizey = 1;
        while (sizey < r) sizey *= 2;
    
        Seg2d seg(sizex, sizey);
        for (int i=0; i<r; i++) {
            for (int j=0; j<c; j++) {
                unsigned int g;
    
                scanf("%u", &g);
                seg.update(j, i, g);
            }
        }
 
        for (int i=0; i<q; i++) {
            int r1, r2;
            int c1, c2;
    
            scanf("%d %d %d %d", &r1, &c1, &r2, &c2);
            printf("%u\n", seg.getMin(c1, c2+1, r1, r2+1));
        }
    }
}

Measured memory_bytes: 17424