#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
ifstream fi("matrice2.in");
ofstream fo("matrice2.out");
using pii = pair<int, int>;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
const int N = 305, LG = 17;
vector<int> g[N * N];
int mx[N][N], lvl[N * N], val[N * N], dsu[N * N], far[LG][N * N], mn_far[LG][N * N];
vector<int> nodes;
int n, q;
static int get_far(int u) {
return (dsu[u] ? (dsu[u] = get_far(dsu[u])) : u); }
static bool join(int a, int b) {
a = get_far(a);
b = get_far(b);
if (a == b)
return false;
if (rand() % 2)
swap(a, b);
dsu[a] = b;
return true; }
static pii get_pos(int cod) {
cod-= 1;
return pii(cod / n + 1, cod % n + 1); }
static int get_cod(int x, int y) {
return (x - 1) * n + y; }
static bool ok(int x, int y) {
return (1 <= min(x, y) && max(x, y) <= n); }
static void build_mst() {
nodes.resize(n * n);
iota(begin(nodes), end(nodes), 1);
sort(begin(nodes), end(nodes), [&](const int &a, const int &b) {
pii pa(get_pos(a)), pb(get_pos(b));
return mx[pa.x][pa.y] > mx[pb.x][pb.y]; });
for (auto i: nodes) {
pii pos = get_pos(i);
int nx, ny, him;
for (int dir = 0; dir < 4; ++dir) {
nx = pos.x + dx[dir];
ny = pos.y + dy[dir];
him = get_cod(nx, ny);
if (!ok(nx, ny))
continue;
if (val[him] < val[i])
continue;
him = get_cod(nx, ny);
if (join(i, him)) {
g[i].push_back(him);
g[him].push_back(i); } } } }
static void dfs(int u, int pap = 0) {
far[0][u] = pap;
mn_far[0][u] = val[u];
for (auto v: g[u]) if (v != pap) {
lvl[v] = lvl[u] + 1;
dfs(v, u); } }
static void build_rmq() {
for (int lg = 1; lg < LG; ++lg)
for (int i = 1; i <= n * n; ++i) {
mn_far[lg][i] = min(mn_far[lg - 1][i], mn_far[lg - 1][far[lg - 1][i]]);
far[lg][i] = far[lg - 1][far[lg - 1][i]]; } }
static int query(int a, int b) {
if (a == b)
return val[a];
if (lvl[a] < lvl[b])
swap(a, b);
int ant = min(val[a], val[b]);
for (int lg = 0; lg < LG; ++lg)
if ((lvl[a] - lvl[b]) & (1 << lg)) {
ant = min(ant, mn_far[lg][a]);
a = far[lg][a]; }
if (a == b)
return ant;
for (int lg = LG - 1; lg >= 0; --lg)
if (far[lg][a] != far[lg][b]) {
ant = min(ant, mn_far[lg][a]);
ant = min(ant, mn_far[lg][b]);
a = far[lg][a];
b = far[lg][b]; }
ant = min(ant, mn_far[0][a]);
ant = min(ant, mn_far[0][b]);
return min(ant, ant); }
int main() {
int x1, x2, y1, y2;
fi >> n >> q;
for (int t = 1, i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j, ++t) {
fi >> mx[i][j];
val[t] = mx[i][j]; }
build_mst();
dfs(1);
build_rmq();
while (q--) {
fi >> x1 >> y1 >> x2 >> y2;
fo << query(get_cod(x1, y1), get_cod(x2, y2)) << '\n'; }
return 0; }