|
| 1 | +```cpp |
| 2 | +#include <bits/stdc++.h> |
| 3 | +using namespace std; |
| 4 | + |
| 5 | +const int dx[4] = {1,0,-1,0}; |
| 6 | +const int dy[4] = {0,1,0,-1}; |
| 7 | + |
| 8 | +int N, Q; |
| 9 | +char arr[1001][1001]{}; |
| 10 | +int srr[1001][1001]{}; |
| 11 | +int cost[1000001]{}, root[1000001]{}, depth[1000001]{}, par[1000001][20]{}, val[1000001][20]{}; |
| 12 | + |
| 13 | +vector<tuple<int, int, int>> edges; |
| 14 | +vector<vector<int>> v(1000001); |
| 15 | + |
| 16 | +int find(int x) { return x == root[x] ? x : root[x]=find(root[x]); } |
| 17 | + |
| 18 | +int sum(int x, int y, int xx, int yy) { |
| 19 | + return srr[xx][yy] - srr[xx][y-1] - srr[x-1][yy] + srr[x-1][y-1]; |
| 20 | +} |
| 21 | + |
| 22 | +void dfs(int n, int p, int d) { |
| 23 | + par[n][0] = p, depth[n] = d; |
| 24 | + for(int i:v[n]) if(i != p) { |
| 25 | + dfs(i,n,d+1); |
| 26 | + val[i][0] = cost[n]; |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +int main(){ |
| 31 | + cin.tie(0)->sync_with_stdio(0); |
| 32 | + |
| 33 | + cin>>N; |
| 34 | + for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) { |
| 35 | + cin>>arr[i][j]; |
| 36 | + srr[i][j] = (arr[i][j] == '#' ? 1 : 0) + srr[i-1][j] + srr[i][j-1] - srr[i-1][j-1]; |
| 37 | + } |
| 38 | + |
| 39 | + for(int i=1;i<=N;i++) for(int j=1;j<=N;j++) if(arr[i][j] != '#') { |
| 40 | + int s = 0; |
| 41 | + int e = min({abs(i-1), abs(N-i), abs(j-1), abs(N-j)}); |
| 42 | + int m = (s+e+1)>>1; |
| 43 | + while(s<e) { |
| 44 | + if(sum(i-m,j-m,i+m,j+m)) e = m-1; |
| 45 | + else s = m; |
| 46 | + m = (s+e+1)>>1; |
| 47 | + } |
| 48 | + cost[(i-1)*N+j] = 2*m+1; |
| 49 | + } |
| 50 | + |
| 51 | + for(int i=0;i<N;i++) for(int j=0;j<N;j++) { |
| 52 | + for(int k=0;k<4;k++) { |
| 53 | + int x = i+dx[k], y = j+dy[k]; |
| 54 | + if(x<0 || x>=N || y<0 || y>=N) continue; |
| 55 | + int c = min(cost[i*N+j+1], cost[x*N+y+1]); |
| 56 | + edges.emplace_back(c, i*N+j+1, x*N+y+1); |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + sort(edges.begin(), edges.end(), greater<>()); |
| 61 | + iota(root, root+N*N+1, 0); |
| 62 | + for(auto [c,a,b] : edges) { |
| 63 | + int x = find(a), y = find(b); |
| 64 | + if(x == y) continue; |
| 65 | + root[x] = y; |
| 66 | + v[a].push_back(b); |
| 67 | + v[b].push_back(a); |
| 68 | + } |
| 69 | + |
| 70 | + dfs(1,0,0); |
| 71 | + for(int k=1;k<20;k++) for(int i=1;i<=N*N;i++) { |
| 72 | + par[i][k] = par[par[i][k-1]][k-1]; |
| 73 | + val[i][k] = min(val[i][k-1], val[par[i][k-1]][k-1]); |
| 74 | + } |
| 75 | + |
| 76 | + for(cin>>Q;Q--;) { |
| 77 | + int a,b,c,d; |
| 78 | + cin>>a>>b>>c>>d; |
| 79 | + int aa = (a-1)*N+b, bb = (c-1)*N+d; |
| 80 | + |
| 81 | + int res = min(cost[aa], cost[bb]); |
| 82 | + int diff = abs(depth[aa] - depth[bb]); |
| 83 | + for(int k=0;k<20;k++) if(diff & (1<<k)) { |
| 84 | + if(depth[aa] > depth[bb]) { |
| 85 | + res = min(res, val[aa][k]); |
| 86 | + aa = par[aa][k]; |
| 87 | + } |
| 88 | + else { |
| 89 | + res = min(res, val[bb][k]); |
| 90 | + bb = par[bb][k]; |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + for(int k=19;k>=0;k--) if(par[aa][k] != par[bb][k]) { |
| 95 | + res = min({res, val[aa][k], val[bb][k]}); |
| 96 | + aa = par[aa][k]; |
| 97 | + bb = par[bb][k]; |
| 98 | + } |
| 99 | + if(aa != bb) { |
| 100 | + res = min({res, val[aa][0], val[bb][0]}); |
| 101 | + } |
| 102 | + |
| 103 | + cout<<res<<'\n'; |
| 104 | + } |
| 105 | + |
| 106 | +} |
| 107 | +``` |
0 commit comments