// Slower C++ solution:
#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <algorithm>

#include <vector>

#include <set>

using namespace std;

const int maxn=1500032;



int mm[maxn*4];

int aa[maxn];

int S, inf, L, r1, c1, r2, c2;

void init(int s, int x, int l, int r)

{

	if (s==0) if (s+x>S) S=s+x;

	if (l==r) { mm[s+x]=aa[l]; //printf("ll %d %d \n", l, aa[l]); 

	return ; }

    int m=(l+r)>>1;

	init(s, x*2, l, m); init(s, x*2+1, m+1, r);

	mm[s+x]=min(mm[s+x*2], mm[s+x*2+1]);

    //printf("nb %d %d\n", s+x, mm[s+x]);

}



int query(int s, int x, int l, int r, int L, int R)

{

	if (L<=l && r<=R) return  mm[s+x];

	int m=(l+r)>>1;

	int ans=inf;

	if (L<=m) ans=min(ans, query(s, 2*x, l, m, L, R));

	if (R>=m+1) ans=min(ans, query(s, 2*x+1, m+1, r, L, R)); 

    return ans;

}



int r, c, q;

int main() 

{

    while (scanf("%d %d %d", &r, &c, &q)!=-1)

	{

		if (r==0 && c==0 && q==0) break;

	    for (int i=0; i<r; i++) 

			for (int j=0; j<c; j++)

		if (r<=c) scanf("%d", &aa[i*c+j+1]); else scanf("%d", &aa[j*r+i+1]); 

		//puts("aa");

        inf=0;

		for (int i=1; i<=r*c; i++) 

		{

			inf=max(inf, aa[i]);

		    //printf("list %d %d\n", i, aa[i]);

		}

		if (r<=c)

		{

			S=0;

			L=c;

			init(0, 1, 1, c);

			//printf("%d %d\n", mm[1], S);

            for (int i=2; i<=r; i++)

			{

				init(S*(i-1), 1, 1+(i-1)*L, i*L);

		        //printf("%d\n", mm[S*(i-1)+1]);

            }

		} else

		{

			S=0;

			L=r;

			init(0, 1, 1, r);

			for (int i=2; i<=c; i++)

			{

				init(S*(i-1), 1, 1+(i-1)*L, i*L);

			}

		}

        //puts("bb");

	    while (q--)

		{

			scanf("%d %d %d %d", &r1, &c1, &r2, &c2);

            r1++; r2++; c1++; c2++;

			//printf("%d %d %d %d\n", r1, c1, r2, c2);

			int ans=inf;

			if (r<=c)

			{

				for (int i=r1; i<=r2; i++)

				{

					ans=min(ans, query(S*(i-1), 1, 1+(i-1)*L, i*L, c1+(i-1)*L, c2+(i-1)*L));  

				//    printf("%d\n", ans);

				}

				printf("%d\n", ans);

			} else

			{

				for (int i=c1; i<=c2; i++)

				{

					//for (int j=r1+(i-1)*L; j<=r2+(i-1)*L; j++)

					//	printf("%d %d\n", j, aa[j]); 

					ans=min(ans, query(S*(i-1), 1, 1+(i-1)*L, i*L, r1+(i-1)*L, r2+(i-1)*L));  

				    //printf("eee %d\n", query(S*(i-1), 1, 1+(i-1)*L, i*L, r1+(i-1)*L, r2+(i-1)*L));  

				    //printf("%d\n", ans);

				}

				printf("%d\n", ans);

			}

		}

	}

	return 0;

}

/*

4 2 10

1 2

2 1

0 7

1 2

1 0 2 1

*/

// Faster C++ solution for the same problem (measured speedup: 2.1047750117753905x):
#include <stdio.h>

#include <string.h>

#include <algorithm>



using namespace std;



typedef long long LL;



#define INF 0x7fffffff

#define MAX 1048576

#define MAXN 65535

#define MAXLg 16

#define MAXQ 20000



int A[MAX],Log[MAXN + 1],tableMin[MAXN][MAXLg];



void makeRMinQ(int *a,int s,int t){

	int n = t - s;

	for (int i = s; i < t; ++i) tableMin[i - s][0] = a[i];

	for (int j = 1; (1 << j) <= n; ++j)

		for (int i = s; i + (1 << j) <= t; ++i)

			tableMin[i - s][j] = min(tableMin[i - s][j - 1], tableMin[i - s + (1 << (j - 1))][j - 1]);

}



int QueryMin(int x,int y){

	int p = Log[y - x + 1];

	return min(tableMin[x][p],tableMin[y - (1 << p) + 1][p]);

}



struct query{

    int x1, y1;

    int x2, y2;

}fQ[MAXQ];



int Res[MAXQ];



int main() {

	for (int i = 0, x = 0, cd = 2; i <= MAXN; ++x, cd <<= 1)

		while (i <= MAXN && i < cd)

		    Log[++i] = x;

	int R, C, Q;

	while(scanf("%d%d%d",&R,&C,&Q), R){

        if (R <= C){

            for (int i = 0; i < R; ++i)

                for (int j = 0; j < C; ++j)

                    scanf("%d", &A[i * C + j]);

            for (int q = 0; q < Q; ++q)

                scanf("%d%d%d%d", &fQ[q].x1, &fQ[q].y1, &fQ[q].x2, &fQ[q].y2);

        }else{

            for (int i = 0; i < R; ++i)

                for (int j = 0; j < C; ++j)

                    scanf("%d", &A[j * R + i]);

            swap(R, C);

            for (int q = 0; q < Q; ++q){

                scanf("%d%d%d%d", &fQ[q].x1, &fQ[q].y1, &fQ[q].x2, &fQ[q].y2);

                swap(fQ[q].x1, fQ[q].y1);

                swap(fQ[q].x2, fQ[q].y2);

            }

        }

        for (int q = 0;q < Q; ++q)

            Res[q] = INF;

        int fC = (C-1) / MAXN+1;

        for (int i = 0; i < R; ++i){

            for (int j = 0, k = 0; j < fC; ++j){

                int nk = min(C, k + MAXN);

                makeRMinQ(A, i * C + k, i * C + nk);

                for (int q = 0; q < Q; ++q){

                    if (i < fQ[q].x1 || fQ[q].x2 < i)

                        continue;

                    int cs = max(fQ[q].y1,k);

                    int ct = min(fQ[q].y2,nk - 1);

                    if (cs > ct) continue;

                    Res[q] = min(Res[q],QueryMin(cs - k,ct - k));

                }

                k = nk;

            }

        }

        for (int q = 0; q < Q; ++q)

            printf("%d\n", Res[q]);

    }

    return 0;

}