#include <fstream>
#include <algorithm>
#include <vector>
#include <iomanip>
#define ll long long
using namespace std;
const int NMAX = 300;
const int QMAX = 20000;
int v[NMAX + 1][NMAX + 1];
vector <pair <int, int> > poz[NMAX * NMAX + 1];
struct ob
{
int i1, j1, i2, j2;
int ans;
};
ob query[QMAX + 1];
int n;
vector <int> norm;
int cnt;
int normalize()
{
int i, j;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
norm.push_back(v[i][j]);
sort(norm.begin(), norm.end());
norm.resize(unique(norm.begin(), norm.end()) - norm.begin());
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
v[i][j] = lower_bound(norm.begin(), norm.end(), v[i][j]) - norm.begin();
poz[v[i][j]].push_back({i, j});
}
return norm.size();
}
int di[] = {-1, 1, 0, 0};
int dj[] = {0, 0, -1, 1};
pair <int, int> tata[NMAX + 1][NMAX + 1];
pair <int, int> dad(int a, int b)
{
if (tata[a][b] == make_pair(a, b))
return {a, b};
tata[a][b] = dad(tata[a][b].first, tata[a][b].second);
return tata[a][b];
}
void joint(int a, int b, int c, int d)
{
pair <int, int> x = dad(a, b);
pair <int, int> y = dad(c, d);
tata[x.first][x.second] = y;
}
void combine(int a, int b, int val)
{
for (int k = 0; k < 4; k++)
{
int ni = a + di[k];
int nj = b + dj[k];
if (ni >= 1 and ni <= n and nj >= 1 and nj <= n and
v[ni][nj] >= val)
joint(a, b, ni, nj);
}
}
ifstream cin("matrice2.in");
ofstream cout("matrice2.out");
void bs(int st, int dr, vector <int> &ceva)
{
if (st > dr)
return ;
if (st == dr)
{
for (int x : ceva)
query[x].ans = norm[st];
return ;
}
int i, med = ((st + dr) >> 1);
for (i = med + 1; i <= dr; i++)
for (pair <int, int> x : poz[i])
combine(x.first, x.second, med + 1);
for (i = st; i <= med; i++)
for (pair <int, int> x : poz[i])
tata[x.first][x.second] = x;
vector <int> good, bad;
for (int x : ceva)
if (dad(query[x].i1, query[x].j1) == dad(query[x].i2, query[x].j2))
{
good.push_back(x);
}
else
bad.push_back(x);
if (st != dr)
{
bs(st, med, bad);
bs(med + 1, dr, good);
}
}
signed main()
{
int i, j, q;
cin >> n >> q;
for (i = 1; i <= n; i++)
for (j = 1; j <= n; j++)
{
cin >> v[i][j];
// cout << setw(6) << v[i][j] << " ";
tata[i][j] = {i, j};
}
cnt = normalize();
vector <int> qs;
for (i = 1; i <= q; i++)
{
cin >> query[i].i1 >> query[i].j1 >> query[i].i2 >> query[i].j2;
qs.push_back(i);
}
bs(0, cnt - 1, qs);
for (i = 1; i <= q; i++)
cout << query[i].ans << "\n";
}