#include <fstream>
#include <algorithm>
#include <list>
#include <vector>
#define MAXN 305
#define MAXQ 20005
using namespace std;
struct elv{
int val,x,y;};
int n,q,matr[MAXN][MAXN],cnt,cnt2,x1,y11,x2,y2,q2[4][MAXQ],cc[MAXN][MAXN],sol[MAXQ],mx,dirx[4]={0,0,1,-1},diry[4]={1,-1,0,0};
elv v[MAXN*MAXN];
list<int> ccc[MAXN*MAXN][2];
list<int>::iterator it1,it2;
vector<int> schpos,quest[MAXN][MAXN];
bool comp(elv a,elv b);
void schimbare_cc(int a, int b);
int main()
{
int i,j,k;
freopen("matrice2.in","r",stdin);
freopen("matrice2.out","w",stdout);
scanf("%ld%ld",&n,&q);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
scanf("%ld",&matr[i][j]);
v[++cnt].val=matr[i][j];
v[cnt].x=i;
v[cnt].y=j;}
sort(v+1,v+n*n+1,comp);
for(i=1;i<=q;i++){
scanf("%ld%ld%ld%ld",&x1,&y11,&x2,&y2);
q2[0][i]=x1;q2[1][i]=y11;q2[2][i]=x2;q2[3][i]=y2;
quest[x1][y11].push_back(i);
quest[x2][y2].push_back(i);}
for(cnt=1;sol[0]!=q;cnt++){
i=v[cnt].x;
j=v[cnt].y;
schpos.clear();
mx=0;
for(k=0;k<4;k++){
if(cc[i+dirx[k]][j+diry[k]]>mx)
mx=cc[i+dirx[k]][j+diry[k]];}
if(mx){
cc[i][j]=mx;
ccc[mx][0].push_back(i);
ccc[mx][1].push_back(j);
if(quest[i][j].size()){
for(k=0;k<quest[i][j].size();k++)
if(!sol[quest[i][j][k]])
schpos.push_back(quest[i][j][k]);}
for(k=0;k<4;k++){
if(cc[i+dirx[k]][j+diry[k]]&&cc[i+dirx[k]][j+diry[k]]!=mx)
schimbare_cc(cc[i+dirx[k]][j+diry[k]],mx);}}
else{
cc[i][j]=++cnt2;
ccc[cnt2][0].push_back(i);
ccc[cnt2][1].push_back(j);}
for(k=0;k<schpos.size();k++){
x1=schpos[k];
if(cc[q2[0][x1]][q2[1][x1]]==cc[q2[2][x1]][q2[3][x1]]&&!sol[x1]){
sol[0]++;
sol[x1]=v[cnt].val;}}}
for(i=1;i<=q;i++)
printf("%ld\n",sol[i]);
return 0;
}
bool comp(elv a, elv b){
return a.val>b.val;}
void schimbare_cc(int a, int b){
int k;
for(it1=ccc[a][0].begin(),it2=ccc[a][1].begin();it1!=ccc[a][0].end();it1++,it2++){
cc[*it1][*it2]=b;
if(quest[*it1][*it2].size()){
for(k=0;k<quest[*it1][*it2].size();k++)
if(!sol[quest[*it1][*it2][k]])
schpos.push_back(quest[*it1][*it2][k]);}}
ccc[b][0].splice(ccc[b][0].end(),ccc[a][0]);
ccc[b][1].splice(ccc[b][1].end(),ccc[a][1]);}