#include #include using namespace std; using namespace atcoder; vector di = {-1, 0, 1, 0}; vector dj = {0, 1, 0, -1}; int main() { int h, w; cin >> h >> w; vector> a(h, vector(w)); vector>> grid(h * w + 1); for (int i = 0; i < h; i++) { for (int j = 0; j < w; j++) { cin >> a[i][j]; grid[a[i][j]].push_back({i, j}); } } auto inc = [&](int i, int j) { return (0 <= i && i < h && 0 <= j && j < w); }; int q; cin >> q; vector rs(q), cs(q), rt(q), ct(q); for (int i = 0; i < q; i++) { cin >> rs[i] >> cs[i] >> rt[i] >> ct[i]; rs[i]--; cs[i]--; rt[i]--; ct[i]--; } vector ok(q, h * w), ng(q, 0); auto finish = [&]() { for (int i = 0; i < q; i++) { if (ok[i] - ng[i] > 1) { return false; } } return true; }; while (!finish()) { vector> mids(h * w + 1); for (int i = 0; i < q; i++) { int mid = (ok[i] + ng[i]) / 2; mids[mid].push_back(i); } dsu uf(h * w); for (int i = 0; i <= h * w; i++) { for (auto [x, y] : grid[i]) { for (int k = 0; k < 4; k++) { int nx = x + di[k], ny = y + dj[k]; if (!inc(nx, ny)) { continue; } if (a[nx][ny] <= i) { uf.merge(w * x + y, w * nx + ny); } } } for (int id : mids[i]) { if (uf.same(w * rs[id] + cs[id], w * rt[id] + ct[id])) { ok[id] = i; } else { ng[id] = i; } } } } for (int i = 0; i < q; i++) { cout << ok[i] << endl; } }