#include <bits/stdc++.h>
#define pb push_back
#define pii pair<int, int>
using ll = long long;
using namespace std;
const int NMAX = 305;
const int QMAX = 2e4 + 5;
/*******************************/
// INPUT / OUTPUT
ifstream f("matrice2.in");
ofstream g("matrice2.out");
/*******************************/
/// GLOBAL DECLARATIONS
int N, Q;
int query_ans[QMAX];
int grid[NMAX][NMAX], h[NMAX][NMAX];
pii par[NMAX][NMAX];
struct Query
{
int x1, y1, x2, y2, val, idx;
const bool operator < (const Query &other) const {
if (val == other.val)
{
return idx < other.idx;
}
return val > other.val;
}
};
struct Tile
{
int x, y, val;
};
vector <Query> queries, new_queries;
vector <Tile> tiles;
vector <int> dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
/*******************************/
/// FUNCTIONS
void ReadInput();
void Solution();
void Output();
/*******************************/
///-------------------------------------
inline void ReadInput()
{
f >> N >> Q;
for (int i = 1 ; i <= N ; ++ i)
{
for (int j = 1 ; j <= N ; ++ j)
{
f >> grid[i][j];
tiles.push_back({i, j, grid[i][j]});
}
}
int x1, y1, x2, y2;
for (int i = 0 ; i < Q ; ++ i)
{
f >> x1 >> y1 >> x2 >> y2;
queries.push_back({x1, y1, x2, y2, 0, i});
}
}
///-------------------------------------
bool comp_tiles(const Tile &a, const Tile &b)
{
return a.val > b.val;
}
///-------------------------------------
inline void init_paduri()
{
for (int i = 1 ; i <= N ; ++ i)
{
for (int j = 1 ; j <= N ; ++ j)
{
par[i][j] = {i, j};
h[i][j] = 1;
}
}
}
///-------------------------------------
pii find(int x, int y)
{
if (par[x][y].first == x && par[x][y].second == y) return par[x][y];
par[x][y] = find(par[x][y].first, par[x][y].second);
return par[x][y];
}
///-------------------------------------
void uneste(pii a, pii b)
{
pii aa = find(a.first, a.second), bb = find(b.first, b.second);
if (h[aa.first][aa.second] < h[bb.first][bb.second])
swap(aa, bb);
h[aa.first][aa.second] += h[bb.first][bb.second];
par[bb.first][bb.second] = aa;
}
///-------------------------------------
void solve_queries(int step)
{
init_paduri();
// for (auto q: queries)
// g << q.x1 << " " << q.y1 << " " << q.x2 << " " << q.y2 << " " << q.val << "\n";
// g << "//-----------------------------\n";
int qIdx = 0, xx, yy;
Tile t;
new_queries.clear();
for (int k = 0 ; k < tiles.size() ; ++ k)
{
t = tiles[k];
for (int i = 0 ; i < 4 ; ++ i)
{
xx = t.x + dx[i];
yy = t.y + dy[i];
if (grid[xx][yy] >= t.val && find(t.x, t.y) != find(xx, yy))
uneste({t.x, t.y}, {xx, yy});
}
if (k != tiles.size() - 1 && t.val == tiles[k + 1].val) continue;
while (qIdx < Q && queries[qIdx].val + step >= t.val)
{
if (find(queries[qIdx].x1, queries[qIdx].y1) == find(queries[qIdx].x2, queries[qIdx].y2))
{
query_ans[queries[qIdx].idx] += step;
}
++ qIdx;
}
}
for (auto q: queries)
new_queries.push_back({q.x1, q.y1, q.x2, q.y2, query_ans[q.idx], q.idx});
sort(new_queries.begin(), new_queries.end());
queries = new_queries;
}
///-------------------------------------
inline void Solution()
{
sort(tiles.begin(), tiles.end(), comp_tiles);
sort(queries.begin(), queries.end());
int p = (1 << 20), s = 0;
while (p)
{
solve_queries(p);
p >>= 1;
}
}
///-------------------------------------
inline void Output()
{
for (int i = 0 ; i < Q ; ++ i)
g << query_ans[i] << "\n";
}
///-------------------------------------
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
ReadInput();
Solution();
Output();
return 0;
}