#include <cstdio>
#include <algorithm>
#define QMax 20000
#define NMax 300
#define lim 1e6
#define x first
#define y second
using namespace std;
struct matrix{int x,i,j;} v[NMax*NMax+1];
pair<int, int> tata[NMax+1][NMax+1];
pair<int, int> q[QMax+1];
int a[NMax+1][NMax+1];
int stiva[QMax+1];
int COADA[QMax+1];
int mid[QMax+1];
int res[QMax+1];
int qx1[QMax+1];
int qy1[QMax+1];
int qx2[QMax+1];
int qy2[QMax+1];
int N,Q;
int dirx[4] = {-1,0,1,0};
int diry[4] = {0,1,0,-1};
pair<int, int> Find(int x, int y)
{
int xr=x,yr=y,x2,xp,yp;
while(tata[xr][yr].x != xr || tata[xr][yr].y != yr) { x2 = xr; xr = tata[xr][yr].x; yr = tata[x2][yr].y; }
while(tata[x][y].x != x || tata[x][y].y != y){
xp = tata[x][y].x;
yp = tata[x][y].y;
tata[x][y] = {xr,yr};
x = xp;
y = yp;
}
return {xr,yr};
}
inline void Union(int x1, int y1, int x2, int y2)
{
pair<int, int> t1, t2;
t1 = Find(x1,y1);
t2 = Find(x2,y2);
tata[t1.x][t1.y] = t2;
}
bool cmp(const matrix A, const matrix B)
{
return A.x > B.x;
}
inline bool in(int x, int y)
{
return (x >= 1 && x <= N && y >= 1 && y <= N);
}
int main(){
FILE* fin = fopen("matrice2.in","r");
FILE* fout = fopen("matrice2.out","w");
int i,j,t,x,y,k,top,sf;
fscanf(fin,"%d %d",&N,&Q);
for(i = 1; i <= N; ++i)
for(j = 1; j <= N; ++j)
{
fscanf(fin,"%d",&x);
v[(i-1)*N+j] = {x,i,j};
tata[i][j] = {i,j};
a[i][j] = x;
}
sort(v+1,v+N*N+1,cmp);
for(i = 1; i <= Q; ++i) fscanf(fin,"%d %d %d %d",&qx1[i],&qy1[i],&qx2[i],&qy2[i]);
for(i = 1; i <= Q; ++i) q[i] = {1,lim};
for(i = 1; i <= Q; ++i) COADA[i] = i;
while(q[ COADA[1] ].x <= q[ COADA[1] ].y){
top = sf = 0;
t = 1;
for(i = 1; i <= Q; ++i) mid[i] = (q[ COADA[i] ].x + q[ COADA[i] ].y) / 2;
for(i = 1; i <= Q; i = j+1)
{
for(j = i; j <= Q && mid[j] == mid[j+1]; ++j);
for(; t <= N*N && v[t].x >= mid[j]; ++t)
for(k = 0; k < 4; ++k)
{
x = v[t].i + dirx[k];
y = v[t].j + diry[k];
if(in(x,y) && a[x][y] >= mid[j]) Union(x,y,v[t].i,v[t].j);
}
for(k = i; k <= j; ++k)
{
x = COADA[k];
if(Find(qx1[x], qy1[x]) == Find(qx2[x], qy2[x])){
res[x] = mid[k];
COADA[++sf] = x;
q[x].x = mid[k]+1;
} else {
stiva[++top] = x;
q[x].y = mid[k]-1;
}
}
while(top) COADA[++sf] = stiva[top--];
}
for(i = 1; i <= N; ++i)
for(j = 1; j <= N; ++j)
tata[i][j] = {i,j};
}
for(i = 1; i <= Q; ++i) fprintf(fout,"%d\n",res[i]);
return 0;
}