#include <cstdio>
#include <algorithm>
using namespace std;
const int nmx = 302, qst = 20002;
const int p1[] = {0,0,1,-1}, p2[] = {1,-1,0,0};
struct nod
{
int i,j;
} v[nmx*nmx];
struct question
{
int x1,y1,x2,y2;
int st,dr;
int cata;
} qs[qst];
int n,m,mat[nmx][nmx],ans[qst];
int tata[nmx*nmx],rang[nmx*nmx];
struct Cmp1
{
bool operator() (nod n1, nod n2)
{
return mat[n1.i][n1.j] > mat[n2.i][n2.j];
}
} cmp1;
struct Cmp2
{
bool operator() (question q1, question q2)
{
return q1.st + q1.dr > q2.st + q2.dr;
}
} cmp2;
int poz(int i, int j)
{
return (i - 1) * n + j;
}
void citire()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= n; ++j)
{
scanf("%d", &mat[i][j]);
int p = poz(i,j);
v[p].i = i;
v[p].j = j;
}
for(int i = 1; i <= m; ++i)
{
scanf("%d %d %d %d", &qs[i].x1, &qs[i].y1, &qs[i].x2, &qs[i].y2);
qs[i].cata = i;
}
}
void reset_paduri()
{
for(int i = 1; i <= n * n; ++i)
{
tata[i] = i;
rang[i] = 1;
}
}
int da_grupa(int ni)
{
int naux = ni;
while(tata[naux] != naux)
naux = tata[naux];
int naux2;
while(ni != tata[ni])
{
naux2 = tata[ni];
tata[ni] = naux;
ni = naux2;
}
return naux;
}
void uneste(int n1, int n2)
{
if(rang[n1] > rang[n2])
tata[n2] = n1;
else
tata[n1] = n2;
if(rang[n1] == rang[n2])
++ rang[n2];
}
bool apartine(int i, int j)
{
return i > 0 && i <= n && j > 0 && j <= n;
}
void uneste_val(int &p, int val)
{
while(mat[v[p].i][v[p].j] >= val)
{
for(int q = 0; q < 4; ++q)
if(apartine(v[p].i+p1[q],v[p].j+p2[q]) && mat[v[p].i+p1[q]][v[p].j+p2[q]] >= val)
{
int g1 = da_grupa(poz(v[p].i,v[p].j));
int g2 = da_grupa(poz(v[p].i+p1[q],v[p].j+p2[q]));
if(g1 != g2)
uneste(g1,g2);
}
++p;
}
}
void set_questions()
{
for(int i = 1; i <= m; ++i)
qs[i].st = 1, qs[i].dr = mat[v[1].i][v[1].j];
}
void cautbin()
{
set_questions();
bool ok = 1;
while(ok)
{
reset_paduri();
ok = 0;
sort(qs+1,qs+m+1,cmp2);
int pozz = 1;
for(int i = 1; i <= m; ++i)
{
if(qs[i].st > qs[i].dr)
continue;
ok = 1;
int mij = (qs[i].st + qs[i].dr) / 2;
uneste_val(pozz,mij);
int g1 = da_grupa(poz(qs[i].x1,qs[i].y1));
int g2 = da_grupa(poz(qs[i].x2,qs[i].y2));
if(g1 == g2)
{
ans[qs[i].cata] = mij;
qs[i].st = mij + 1;
}
else
qs[i].dr = mij - 1;
}
}
}
void afish()
{
for(int i = 1; i <= m; ++i)
printf("%d\n", ans[i]);
}
int main()
{
freopen("matrice2.in", "r", stdin);
freopen("matrice2.out", "w", stdout);
citire();
sort(v+1,v+n*n+1,cmp1);
/**for(int i = 1; i < 26; ++i)
printf("%d %d %d\n", v[i].i, v[i].j, mat[v[i].i][v[i].j]);**/
cautbin();
afish();
return 0;
}