#include <bits/stdc++.h>
#define maxN 302
#define maxQ 20002
#define pii pair < int, int >
#define f first
#define s second
using namespace std;
int n, q, nr, ans[maxQ], cell, F[maxN * maxN], mat[maxN][maxN];
int dx[] = {0, 1, 0, -1};
int dy[] = {1, 0, -1, 0};
struct query
{
int xa, ya, xb, yb, val, idx;
} v[maxQ];
struct matrix
{
int x, y, val;
} a[maxN * maxN];
int cmp(const query a, const query b)
{
return a.val > b.val;
}
int Cmp(const matrix a, const matrix b)
{
return a.val < b.val;
}
void read()
{
int i, j;
nr = 0;
freopen("matrice2.in", "r", stdin);
scanf("%d %d", &n, &q);
for (i = 1; i <= n; ++ i)
for (j = 1; j <= n; ++ j)
{
scanf("%d", &a[++ nr].val);
mat[i][j] = a[nr].val;
a[nr].x = i;
a[nr].y = j;
}
for (i = 1; i <= q; ++ i)
{
scanf("%d %d %d %d", &v[i].xa, &v[i].ya, &v[i].xb, &v[i].yb);
v[i].idx = i;
}
}
int root(int x)
{
if (!F[x])
return x;
return F[x] = root(F[x]);
}
void lilUnion(int xa, int ya, int xb, int yb)
{
int rx = root((xa - 1) * n + ya), ry = root((xb - 1) * n + yb);
if (rx != ry)
F[rx] = ry;
}
int okc(int x, int y)
{
return (x <= n && y <= n && x > 0 && y > 0);
}
void bigUnion(int X)
{
int d;
while (a[cell].val >= X && cell > 0)
{
int x = a[cell].x, y = a[cell].y;
for (d = 0; d < 4; ++ d)
if (okc(x + dx[d], y + dy[d]) && mat[x + dx[d]][y + dy[d]] >= X)
lilUnion(x, y, x + dx[d], y + dy[d]);
-- cell;
}
}
void BS()
{
int i, p = 1 << 19;
while (p)
{
memset(F, 0, sizeof(F));
cell = nr;
sort(v + 1, v + q + 1, cmp);
for (i = 1; i <= q; ++ i)
{
bigUnion(v[i].val + p);
if (root((v[i].xa - 1) * n + v[i].ya) == root((v[i].xb - 1) * n + v[i].yb))
{
v[i].val += p;
ans[v[i].idx] += p;
}
}
p >>= 1;
}
}
void solve()
{
cell = nr;
sort(a + 1, a + nr + 1, Cmp);
BS();
}
void write()
{
int i;
freopen("matrice2.out", "w", stdout);
for (i = 1; i <= q; ++ i)
printf("%d\n", ans[i]);
}
int main()
{
read();
solve();
write();
return 0;
}