#include <bits/stdc++.h>
using namespace std;
const int MAXN = 305;
const int MAXM = 20005;
struct Node {
int val, ind;
bool operator < (const Node& other) const {
return val > other.val;
}
}v[MAXN * MAXN];
int dx[] = {1, -1, 0, 0};
int dy[] = {0, 0, 1, -1};
vector<int>G[MAXN * MAXN];
struct Query {
int st, dr, last, u, v, ind;
}q[MAXM], s1[MAXM], s2[MAXM];
int t[MAXN * MAXN], h[MAXN * MAXN];
bool viz[MAXN * MAXN];
int f(int x) {
int aux = x;
while (x != t[x])
x = t[x];
while (aux != x) {
int a = t[aux];
t[aux] = x;
aux = a;
}
return x;
}
void u(int x, int y) {
x = f(x);
y = f(y);
if (x == y)
return ;
if (h[x] < h[y])
swap(x, y);
t[y] = x;
if (h[x] == h[y])
h[x]++;
}
void add(int node) {
viz[node] = 1;
for (auto it:G[node])
if (viz[it])
u(it, node);
}
bool ok(int x, int y) {
return (f(x) == f(y));
}
void solve(int n, int m) {
for (int pas = 20; pas > 0; --pas) {
for (int i = 1; i <= n; ++i) {
t[i] = i;
h[i] = 1;
viz[i] = 0;
}
int i = 1, j = 1, k1 = 0, k2 = 0;
while (i <= n && j <= m) {
while (i <= n && v[i].val >= (q[j].st + q[j].dr) / 2)
add(v[i++].ind);
while (j <= m && v[i].val < (q[j].st + q[j].dr) / 2)
if (ok(q[j].u, q[j].v)) {
q[j].last = (q[j].st + q[j].dr) / 2;
q[j].st = (q[j].st + q[j].dr) / 2 + 1;
s1[++k1] = q[j++];
} else {
q[j].dr = (q[j].st + q[j].dr) / 2 - 1;
s2[++k2] = q[j++];
}
}
i = j = 1;
m = 0;
while (i <= k1 && j <= k2) {
if (s1[i].st + s1[i].dr >= s2[j].st + s2[j].dr)
q[++m] = s1[i++];
else
q[++m] = s2[j++];
}
while (i <= k1)
q[++m] = s1[i++];
while (j <= k2)
q[++m] = s2[j++];
}
}
int sol[MAXN];
int main() {
freopen("matrice2.in", "r", stdin);
freopen("matrice2.out", "w", stdout);
int n, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
int x;
scanf("%d", &x);
v[(i - 1) * n + j] = {x, (i - 1) * n + j};
}
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
for (int k = 0; k < 4; ++k) {
int i1 = i + dx[k];
int j1 = j + dy[k];
if (i1 != 0 && i1 != n + 1 && j1 != 0 && j1 != n + 1)
G[(i - 1) * n + j].push_back((i1 - 1) * n + j1);
}
sort(v + 1, v + n * n + 1);
for (int i = 1; i <= m; ++i) {
int x1, y1, x2, y2;
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
q[i] = {1, 1000000, 0, (x1 - 1) * n + y1, (x2 - 1) * n + y2, i};
}
solve(n * n, m);
for (int i = 1; i <= m; ++i)
sol[q[i].ind] = q[i].last;
for (int i = 1; i <= m; ++i)
printf("%d\n", sol[i]);
return 0;
}