#include <algorithm>
#include <stdio.h>
#include <vector>
#define MAX 310
#define MAXQ 20010
#define pb push_back
#define mp make_pair
#define x first
#define y second
using namespace std;
int dirX[] = {-1, 0, 0, 1};
int dirY[] = {0, -1, 1, 0};
int n, q;
int matAlt[MAX][MAX];
int xs[MAXQ], ys[MAXQ], xf[MAXQ], yf[MAXQ], sol[MAXQ], loc[MAXQ];
pair <int, int> vctNr[MAX * MAX];
pair <int, int> t[MAX][MAX];
vector <int> vctQuery;
inline bool cmp(const pair <int, int> &a, const pair <int, int> &b)
{
return matAlt[a.x][a.y] < matAlt[b.x][b.y];
}
inline bool cmpsol(const int &a, const int &b)
{
return sol[a] < sol[b];
}
inline pair <int, int> tata(pair <int, int> nod)
{
if (t[nod.x][nod.y] != nod)
t[nod.x][nod.y] = tata(t[nod.x][nod.y]);
return t[nod.x][nod.y];
}
inline void cautaBin()
{
int step = 1;
for (; step <= 1000000; step *= 2);
for (; step; step /= 2)
{
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
t[i][j] = mp(0, 0);
for (int i = 1; i <= q; i++)
{
sol[i] += step;
loc[i] = i;
}
sort(loc + 1, loc + 1 + q, cmpsol);
reverse(loc + 1, loc + 1 + q);
int l = 1;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
t[i][j] = mp(0, 0);
for (int i = 1; i <= n * n + 1; i++)
{
int x = vctNr[i].x, y = vctNr[i].y;
for (; sol[loc[l]] > matAlt[x][y]; l++)
if (!(t[xs[loc[l]]][ys[loc[l]]] != mp(0, 0) && t[xf[loc[l]]][yf[loc[l]]] != mp(0, 0) && tata(mp(xs[loc[l]], ys[loc[l]])) == tata(mp(xf[loc[l]], yf[loc[l]]))))
sol[loc[l]] -= step;
t[x][y] = mp(x, y);
for (int dir = 0; dir < 4; dir++)
{
if (!(x + dirX[dir]) || (x + dirX[dir] > n) || !(y + dirY[dir]) || (y + dirY[dir] > n) || t[x + dirX[dir]][y + dirY[dir]] == mp(0, 0))
continue;
pair <int, int> p1 = tata(mp(x, y));
pair <int, int> p2 = tata(mp(x + dirX[dir], y + dirY[dir]));
if (p1 != p2)
t[p1.x][p1.y] = tata(mp(p2.x, p2.y));
}
}
}
}
int main()
{
freopen("matrice2.in", "r", stdin);
freopen("matrice2.out", "w", stdout);
scanf("%d %d", &n, &q);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
{
scanf("%d", &matAlt[i][j]);
vctNr[(i - 1) * n + j] = mp(i, j);
}
sort(vctNr + 1, vctNr + 1 + n * n, cmp);
reverse(vctNr + 1, vctNr + 1 + n * n);
for (int i = 1; i <= q; i++)
{
scanf("%d %d %d %d", &xs[i], &ys[i], &xf[i], &yf[i]);
vctQuery.pb(i);
}
cautaBin();
for (int i = 1; i <= q; i++)
printf("%d\n", sol[i]);
fclose(stdin);
fclose(stdout);
return 0;
}