#include #include #include #include #include #include using namespace std; const int MAX = 1010; const int MAXQ = 1000100; struct Query { int r1, c1, r2, c2; } q[MAXQ]; int qans[MAXQ]; char cell[MAX][MAX]; int cell_f[MAX][MAX]; vector> bucket_f[MAX]; vector cell_qs[MAX][MAX]; int N, Q; vector> group_cells[MAX][MAX]; vector group_qs[MAX][MAX]; pair cell_group[MAX][MAX]; void calc_largest_square() { queue> Q; for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { if (cell[i][j] == '.') { cell_f[i][j] = -1; } else { cell_f[i][j] = 0; Q.push({i, j}); } } } while (!Q.empty()) { int x = Q.front().first; int y = Q.front().second; Q.pop(); bucket_f[cell_f[x][y]].push_back({x, y}); for (int dx = -1; dx <= 1; ++dx) { for (int dy = -1; dy <= 1; ++dy) { int nx = x + dx; int ny = y + dy; if (nx >= 0 && nx < N && ny >= 0 && ny < N && cell_f[nx][ny] == -1) { cell_f[nx][ny] = cell_f[x][y] + 1; Q.push({nx, ny}); } } } } } void merge(int x1, int y1, int x2, int y2, int cur_length) { tie(x1, y1) = cell_group[x1][y1]; tie(x2, y2) = cell_group[x2][y2]; if (x1 == x2 && y1 == y2) return; // calculate weights for each group // merge smaller group onto larger one int w1 = group_cells[x1][y1].size() + group_qs[x1][y1].size(); int w2 = group_cells[x2][y2].size() + group_qs[x2][y2].size(); if (w1 > w2) { swap(w1, w2); swap(x1, x2); swap(y1, y2); } // answer queries for (int qi: group_qs[x1][y1]) { int r1 = q[qi].r1, c1 = q[qi].c1; int r2 = q[qi].r2, c2 = q[qi].c2; if ((cell_group[r1][c1] == make_pair(x1, y1) && cell_group[r2][c2] == make_pair(x2, y2)) || (cell_group[r1][c1] == make_pair(x2, y2) && cell_group[r2][c2] == make_pair(x1, y1))) { qans[qi] = cur_length; } } // merge groups for (int qi: group_qs[x1][y1]) { group_qs[x2][y2].push_back(qi); } group_qs[x1][y1].clear(); for (auto& cell: group_cells[x1][y1]) { cell_group[cell.first][cell.second] = {x2, y2}; group_cells[x2][y2].push_back(cell); } group_cells[x1][y1].clear(); } int main(void) { scanf("%d", &N); for (int i = 1; i <= N; ++i) scanf("%s", cell[i] + 1); N += 2; scanf("%d", &Q); for (int i = 0; i < Q; ++i) { int r1, c1, r2, c2; scanf("%d %d %d %d", &r1, &c1, &r2, &c2); q[i] = {r1, c1, r2, c2}; cell_qs[r1][c1].push_back(i); cell_qs[r2][c2].push_back(i); } calc_largest_square(); static bool bio[MAX][MAX]; for (int d = N; d >= 0; --d) { for (auto& p: bucket_f[d]) { int x = p.first; int y = p.second; group_cells[x][y] = {{x, y}}; group_qs[x][y] = cell_qs[x][y]; cell_group[x][y] = {x, y}; bio[x][y] = true; static int dx[] = {1, 0, -1, 0}; static int dy[] = {0, 1, 0, -1}; for (int k = 0; k < 4; ++k) { int nx = x + dx[k]; int ny = y + dy[k]; if (nx >= 0 && nx < N && ny >= 0 && ny < N && bio[nx][ny]) { merge(x, y, nx, ny, d); } } } } for (int i = 0; i < Q; ++i) { int ans = qans[i] ? 2*qans[i]-1 : 0; printf("%d\n", ans); } return 0; }