#include <fstream>
#include <algorithm>
#include <cstring>
#include <set>
#include <queue>
using namespace std;
#define MAXN 310
#define inf 1<<30
#define x first
#define y second
set<int> s;
int A[MAXN][MAXN],N,Q,dx[] = {-1, 0, +1, 0},dy[] = {0, +1, 0, -1};
int dist[MAXN][MAXN];
int bfs(int x1,int y1,int x2,int y2, int h)
{
memset(dist,0,sizeof(dist));
pair<int, int> nod;
queue<pair<int, int> > Q;
if(A[x1][y1] < h) return 0;
Q.push(make_pair(x1,y1));
dist[x1][y1] = 1;
while(!Q.empty())
{
nod = Q.front();
Q.pop();
for(int i=0;i<4;i++)
if(dist[nod.x + dx[i]][nod.y+dy[i]]==0 && A[nod.x + dx[i]][nod.y + dy[i]] >= h)
{
dist[nod.x +dx[i]][nod.y+dy[i]]=1;
if(nod.x + dx[i]==x2 && nod.y + dy[i] == y2) return 1;
Q.push(make_pair(nod.x +dx[i],nod.y+dy[i]));
}
}
return 0;
}
int main()
{
ifstream f("matrice2.in");
ofstream g("matrice2.out");
int sol,x1,x2,y1,y2,a,i, j, k, p, step;
f >> N >> Q;
for (i = 1; i <= N; i++)
for (j = 1; j <= N; j++)
{
f>>a;
A[i][j] = a;
s.insert(a);
}
for(i=1;i<=Q;i++)
{
f>>x1>>y1>>x2>>y2;
int p = 0,u = s.size() - 1;
set<int>::iterator it = s.begin();
int mid = (p+u)/2,best=0;
advance(it,mid);
while(p <= u)
{
sol = bfs(x1,y1,x2,y2,*it);
if(sol==0)
{
u = mid;
mid = (p+u)/2;
advance(it,-(u-mid));
}
else
{
p = mid+1;
mid = (p+u)/2;
best = max(*it,best);
advance(it,(mid-p));
}
}
g<<best<<"\n";
}
}