#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
#define maxn 310
#define maxq 20010
#define pb push_back
struct punct
{
long x;
long y;
long id;
};
long n, i, j, k, poz, q, l, p1, p2;
punct q1, q2, p[maxn*maxn];
long tata[maxn*maxn], euler[maxn*maxn*2], ad[maxn*maxn*2], st[maxn*maxn], r[20][maxn*maxn*2], sol[20][maxn*maxn*2], f[maxn*maxn];
long m[maxn][maxn], ind[maxn][maxn], fol[maxn][maxn];
vector <long> v[maxn*maxn];
const long d1[]={0, -1, 0, 1};
const long d2[]={-1, 0, 1, 0};
inline int cmp(punct a, punct b)
{
return m[a.x][a.y]>m[b.x][b.y];
}
void c_conexe()
{
long i, j, xx, yy, nod, aux;
for(i=1; i<=n*n; i++)
{
tata[i]=i;
}
for(i=1; i<=n*n; i++)
{
fol[p[i].x][p[i].y]=1;
for(j=0; j<4; j++)
{
xx=(p[i].x)+d1[j];
yy=(p[i].y)+d2[j];
if(xx && yy && xx<=n && yy<=n && fol[xx][yy])
{
nod=ind[xx][yy];
while(tata[nod]!=nod)
{
nod=tata[nod];
}
if(nod!=p[i].id)
{
// printf("%d %d\n", nod, p[i].id);
tata[nod]=p[i].id;
v[p[i].id].pb(nod);
nod=ind[xx][yy];
while(tata[nod]!=nod)
{
aux=tata[nod];
tata[nod]=p[i].id;
nod=aux;
}
}
}
}
}
}
void df(long nod, long niv)
{
long i, fiu;
// if(f[nod]) return;
f[nod]=1;
l++;
st[nod]=l;
euler[l]=nod;
ad[l]=niv;
for(i=0; i<v[nod].size(); i++)
{
fiu=v[nod][i];
df(fiu, niv+1);
l++;
euler[l]=nod;
ad[l]=niv;
}
}
void rmq()
{
long i, j, put, e;
for(i=1; i<=l; i++)
{
r[0][i]=ad[i];
sol[0][i]=euler[i];
}
for(put=1, e=1; put<=l; put*=2, e++)
{
for(i=1; i+put-1<=l; i++)
{
r[e][i]=r[e-1][i];
sol[e][i]=sol[e-1][i];
if(r[e-1][i+(put/2)]<r[e][i])
{
r[e][i]=r[e-1][i+(put/2)];
sol[e][i]=sol[e-1][i+(put/2)];
}
// printf("%d ", r[e][i]);
}
// printf("\n");
}
}
long raspunde(long poz1, long poz2)
{
long put, e, s, nod, xx, yy;
put=1;
e=0;
while(put*2<=poz2-poz1+1)
{
put*=2;
e++;
}
s=r[e][poz1];
nod=sol[e][poz1];
// printf("%d ", poz2-put);
if(r[e][poz2-put+1]<s)
{
s=r[e][poz2-put+1];
nod=sol[e][poz2-put+1];
}
// printf("%d ", nod);
xx=nod/n+1;
yy=nod%n;
if(yy==0)
{
yy=n;
xx--;
}
// printf("%d %d\n", xx, yy);
return m[xx][yy];
}
int main()
{
freopen("matrice2.in", "r", stdin);
freopen("matrice2.out", "w", stdout);
scanf("%d%d", &n, &q);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
scanf("%d", &m[i][j]);
poz=(i-1)*n+j;
ind[i][j]=poz;
p[poz].x=i;
p[poz].y=j;
p[poz].id=poz;
}
}
sort(p+1, p+n*n+1, cmp);
c_conexe();
df(p[n*n].id, 1);
rmq();
// printf("\n");
/* for(i=1; i<=n*n; i++)
{
printf("%d: ", i);
for(j=0; j<v[i].size(); j++)
{
printf("%d ", v[i][j]);
}
printf("\n");
}*/
for(i=1; i<=q; i++)
{
scanf("%d%d%d%d", &q1.x, &q1.y, &q2.x, &q2.y);
q1.id=(q1.x-1)*n+q1.y;
q2.id=(q2.x-1)*n+q2.y;
p1=min(st[q1.id], st[q2.id]);
p2=max(st[q1.id], st[q2.id]);
// printf("%d %d\n", p1, p2);
printf("%d\n", raspunde(p1, p2));
}
return 0;
}