meaning of the title
A rectangular N * N map composed of. and #. k I j denotes that the edge length of the largest square centered on (i, j) is k.
For each query from (sx, sy) to (ex, ey), the maximum square edge length k makes it possible to satisfy that there is no
Solving problems
Firstly, the k of each point is solved by flooding algorithm. See flood_fill().
When enumerating point i, it expands in four directions. If point j has been visited, it finds the ancestor node AJ of the same set, links it from I to aj, and combines I through and checks the set.
For each group of questions, the k value of the ancestor point is the maximum value of the answer when the nearest common ancestor is obtained by LCA.
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1000 + 10;
const int dir[8][2] = {-1,0, 1,0, 0,-1, 0,1, -1,-1, -1,1, 1,-1, 1,1};
int n, q, k[N][N], vis[N][N];
char flr[N][N];
pair<int, int> arr[N*N];
bool cmp(pair<int, int> a, pair<int, int> b) {
return a.second > b.second;
}
struct Edge {
int nxt, to;
} e[N*N*2];
int head[N*N], cnt;
void addedge(int u, int v) {
e[++cnt].nxt = head[u];
e[cnt].to = v;
head[u] = cnt;
}
int fa[N*N];
int find(int x) { return fa[x] = fa[x] == x ? x : find(fa[x]); }
void flood_fill()
{
queue<pair<int, int> > que;
pair<int, int> p, q;
memset(k, 0x3f, sizeof(k));
for(int i=0;i<=n+1;i++)
for(int j=0;j<=n+1;j++)
if(flr[i][j] == '#' || i==0 || i==n+1 || j==0 || j==n+1)
que.push(make_pair(i, j)), k[i][j] = -1;
while(!que.empty())
{
p = que.front();
que.pop();
for(int i=0;i<8;i++)
{
q = make_pair(p.first+dir[i][0], p.second+dir[i][1]);
if(q.first<=0 || q.first>n || q.second<=0 || q.second>n || k[q.first][q.second] != 0x3f3f3f3f) continue;
k[q.first][q.second] = k[p.first][p.second] + 2;
que.push(q);
}
if(k[p.first][p.second] == -1) k[p.first][p.second] = 0;
}
}
void solve(int r, int c)
{
vis[r][c] = 1;
for(int i=0, nr, nc;i<4;i++)
{
nr = r + dir[i][0];
nc = c + dir[i][1];
if(nr<=0 || nr>n || nc<=0 || nc>n || vis[nr][nc] == 0) continue;
int x = find((nr-1)*n+nc-1);
int y = find((r-1)*n+c-1);
if(x == y) continue;
fa[x] = y;
addedge(y, x); addedge(x, y);
}
}
const int maxh = 20;
int dep[N*N];
int anc[N*N][20];
void dfs(int rt) {
static int Stack[N*N];
int top = 0;
dep[rt] = 1;
for(int i=0;i<maxh;i++)
anc[rt][i] = rt;
Stack[++top] = rt;
while(top) {
int x = Stack[top];
if(x != rt) {
for(int i=1, y;i<maxh;i++)
y = anc[x][i-1], anc[x][i] = anc[y][i-1];
}
for(int &i=head[x];i;i=e[i].nxt) {
int y = e[i].to;
if(y != anc[x][0]) {
dep[y] = dep[x] + 1;
anc[y][0] = x;
Stack[++top] = y;
}
}
while(top && head[Stack[top]] == 0) top--;
}
}
void swim(int &x, int H) {
for(int i=0;H;i++) {
if(H & 1) x = anc[x][i];
H /= 2;
}
}
int lca(int x, int y) {
int i;
if(dep[x] > dep[y]) swap(x, y);
swim(y, dep[y]-dep[x]);
if(x == y) return x;
for(;;) {
for(i=0;anc[x][i] != anc[y][i];i++);
if(i == 0) return anc[x][0];
x = anc[x][i-1];
y = anc[y][i-1];
}
return -1;
}
int main()
{
while(scanf("%d", &n)!=EOF)
{
for(int i=1;i<=n;i++)
scanf(" %s", flr[i]+1);
// Calculate the maximum k of each point.
flood_fill();
for(int i=1, x;i<=n;i++)
for(int j=1;j<=n;j++)
{
x = (i-1)*n+j-1;
arr[x].first = x;
arr[x].second = k[i][j];
}
sort(arr, arr+n*n, cmp);
for(int i=0;i<=n*n;i++)
fa[i] = i;
memset(vis, 0, sizeof(vis));
for(int i=0, x;i<n*n;i++) {
x = arr[i].first;
solve(x/n+1, x%n+1);
}
dfs(arr[n*n-1].first);
scanf("%d", &q);
for(int i=0, sx, sy, ex, ey;i<q;i++)
{
scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
int pointIdx = lca((sx-1)*n+sy-1, (ex-1)*n+ey-1);
printf("%d\n", k[pointIdx/n+1][pointIdx%n+1]);
}
}
}