#include <cstdio>
#include <algorithm>
using namespace std;
#define lmax 90010
#define mmax 20010
#define nmax 310
int v1[4]={0,0,1,-1};
int v2[4]={1,-1,0,0};
int n, m, l, u[nmax][nmax], ind[nmax][nmax], t[lmax];
struct elem
{
int val, x, y;
} v[lmax];
int cmp(elem a, elem b)
{
return a.val>b.val;
}
struct query
{
int x1, y1, x2, y2, sol, ind;
} q[mmax];
int cmp2(query a, query b)
{
return a.sol > b.sol;
}
int cmp3(query a, query b)
{
return a.ind < b.ind;
}
int root (int x)
{
if (x!=t[x]) t[x]=root(t[x]);
return t[x];
}
int main()
{
freopen("matrice2.in","r",stdin);
freopen("matrice2.out","w",stdout);
scanf("%d %d", &n, &m);
int i, j, h=0, x, y, cx, cy, step, p, k, pos;
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
{
scanf("%d", &v[++h].val);
v[h].x=i;
v[h].y=j;
}
l=n*n;
sort (v+1, v+l+1, cmp);
for (i=1; i<=l; i++)
ind[v[i].x][v[i].y]=i;
for (i=1; i<=m; i++)
{
scanf("%d %d %d %d",&q[i].x1, &q[i].y1, &q[i].x2, &q[i].y2);
q[i].ind=i;
}
for (step=1; step<v[1].val; step<<=1);
for ( ; step>0; step >>=1)
{
sort (q+1, q+m+1, cmp2);
for (i=1; i<=n; i++)
for (j=1; j<=n; j++) u[i][j]=0;
for (i=1; i<=l; i++) t[i]=i;
j=1;
for (i=1; i<=l; )
{
for (; j<=m && q[j].sol+step>v[i].val; j++)
if (root (ind[q[j].x1][q[j].y1]) == root (ind[q[j].x2][q[j].y2])) q[j].sol+=step;
pos=i;
for (; i<=l && v[i].val==v[pos].val; i++)
{
x=v[i].x;
y=v[i].y;
u[x][y]=1;
for (k=0; k<4; k++)
{
cx = x + v1[k];
cy = y + v2[k];
if (cx>0 && cy>0 && cx<=n && cy<=n && u[cx][cy])
{
p=ind[cx][cy];
t[root(p)]=root(i);
}
}
}
}
for (; j<=m; j++)
if (root (ind[q[j].x1][q[j].y1]) == root (ind[q[j].x2][q[j].y2])) q[j].sol+=step;
}
sort (q+1, q+m+1, cmp3);
for (i=1; i<=m; i++) printf("%d\n",q[i].sol);
}