#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 300
#define MAXQ 20000
int n, r;
int v[MAXN * MAXN], p[MAXN * MAXN];
int q1[MAXQ], q2[MAXQ], utq[MAXN * MAXN], nxtq1[MAXQ], nxtq2[MAXQ], qr[MAXQ];
int comp[MAXN * MAXN], ut[MAXN * MAXN], nxt[MAXN * MAXN], nrc[MAXN * MAXN];
bool cmp(int a, int b){
if(v[a] > v[b])
return 1;
return 0;
}
inline void unesc(int a, int b){
if(comp[a] != comp[b]){
int aux, c1, c2, p, pq, np;
if(nrc[comp[a]] < nrc[comp[b]]){
aux = a; a = b; b = aux;
}
c1 = comp[a]; c2 = comp[b];
p = ut[comp[b]];
while(p != -1){
pq = utq[p];
while(pq != -1){
if(p == q1[pq]){
if(comp[q2[pq]] == c1 && qr[pq] == -1)
qr[pq] = r;
pq = nxtq1[pq];
}
else{
if(comp[q1[pq]] == c1 && qr[pq] == -1)
qr[pq] = r;
pq = nxtq2[pq];
}
}
comp[p] = c1;
np = nxt[p];
nxt[p] = ut[c1];
ut[c1] = p;
p = np;
}
nrc[c1] += nrc[c2];
nrc[c2] = 0;
}
}
int main(){
FILE *in = fopen("matrice2.in", "r");
int q, i, j, x1, x2, y1, y2, aux;
fscanf(in, "%d%d", &n, &q);
for(i = 0; i < n; i++){
for(j = 0; j < n; j++){
fscanf(in, "%d", &v[i * n + j]);
p[i * n + j] = i * n + j;
}
}
std::sort(p, p + n * n, cmp);
memset(qr, -1, sizeof qr);
memset(utq, -1, sizeof utq);
for(i = 0; i < q; i++){
fscanf(in, "%d%d%d%d", &x1, &y1, &x2, &y2);
x1--; y1--; x2--; y2--;
x1 = x1 * n + y1;
x2 = x2 * n + y2;
if(x1 > x2){
aux = x1; x1 = x2; x2 = aux;
}
q1[i] = x1;
q2[i] = x2;
nxtq1[i] = utq[x1];
nxtq2[i] = utq[x2];
utq[x1] = utq[x2] = i;
}
fclose(in);
for(i = 0; i < n * n; i++){
comp[i] = i;
ut[i] = i;
nxt[i] = -1;
nrc[i] = 1;
}
for(i = 0; i < n * n; i++){
r = v[p[i]];
x1 = p[i] / n;
y1 = p[i] % n;
if(y1 != 0 && v[p[i] - 1] >= r)
unesc(p[i], p[i] - 1);
if(y1 != n - 1 && v[p[i] + 1] >= r)
unesc(p[i], p[i] + 1);
if(x1 != 0 && v[p[i] - n] >= r)
unesc(p[i], p[i] - n);
if(x1 != n - 1 && v[p[i] + n] >= r)
unesc(p[i], p[i] + n);
}
FILE *out = fopen("matrice2.out", "w");
for(i = 0; i < q; i++)
fprintf(out, "%d\n", qr[i]);
fclose(out);
return 0;
}