\(\mathcal{Description}\)

  Link.

  给一个 \(n\times n\) 的网格图,每个点是空格或障碍。\(q\) 次询问,每次给定两个坐标 \((r_1,c_1),(r_2,c_2)\),问最大的正方形边长 \(k\),满足 \(k\) 是奇数,且中心点在 \((r_1,c_1)\) 的正方形能够移动成为中心点在 \((r_2,c_2)\) 的正方形。

  \(n\le1000\),\(q\le3\times10^5\)。

\(\mathcal{Solution}\)

  这题咋黑了呢 owo?

  令障碍为 \(1\),空格为 \(0\),则一个正方形合法等价于子矩阵和为 \(0\),单次判断用前缀和做到 \(\mathcal O(1)\)。然后整体二分即可。

  复杂度 \(\mathcal O((n^2+q)\log n)\)。

\(\mathcal{Code}\)

#include <queue>
#include <cstdio>
#include <vector> typedef std::pair<int, int> pii; const int MAXN = 1000, MAXQ = 3e5;
const int MOVE[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
int n, q, sum[MAXN + 5][MAXN + 5];
int ans[MAXQ + 5], color[MAXN + 5][MAXN + 5];
std::vector<pii> arrived; struct Query { int r1, c1, r2, c2, id; };
std::vector<Query> qrys; inline int rint () {
int x = 0; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () );
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x;
} inline void wint ( const int x ) {
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
} inline bool legal ( const int r, const int c, const int rad ) {
int r1 = r - rad, c1 = c - rad, r2 = r + rad - 1, c2 = c + rad - 1;
return 0 <= r1 && 0 <= c1 && r2 <= n && c2 <= n
&& ! ( sum[r2][c2] - sum[r2][c1] - sum[r1][c2] + sum[r1][c1] );
} inline void paint ( const int sr, const int sc, const int rad, const int c ) {
static std::queue<pii> que;
que.push ( { sr, sc } ), color[sr][sc] = c;
arrived.push_back ( { sr, sc } );
while ( ! que.empty () ) {
pii p = que.front (); que.pop ();
for ( int w = 0, tx, ty; w < 4; ++ w ) {
tx = p.first + MOVE[w][0], ty = p.second + MOVE[w][1];
if ( ! color[tx][ty] && legal ( tx, ty, rad ) ) {
que.push ( { tx, ty } ), color[tx][ty] = c;
arrived.push_back ( { tx, ty } );
}
}
}
} inline void solve ( std::vector<Query>& curq, const int al, const int ar ) {
if ( curq.empty () ) return ;
if ( al == ar ) {
for ( auto q: curq ) ans[q.id] = al ? ( al << 1 ) - 1 : 0;
return ;
}
int amid = al + ar + 1 >> 1, col = 0;
for ( int i = amid, ei = n - amid + 1; i <= ei; ++ i ) {
for ( int j = amid, ej = n - amid + 1; j <= ej; ++ j ) {
if ( ! color[i][j] && legal ( i, j, amid ) ) {
paint ( i, j, amid, ++ col );
}
}
}
std::vector<Query> vecL, vecR;
for ( auto q: curq ) {
if ( color[q.r1][q.c1] && color[q.r1][q.c1] == color[q.r2][q.c2] ) vecR.push_back ( q );
else vecL.push_back ( q );
}
for ( pii c: arrived ) color[c.first][c.second] = 0;
arrived.clear ();
solve ( vecL, al, amid - 1 ), solve ( vecR, amid, ar );
} int main () {
n = rint ();
char tmp[MAXN + 5];
for ( int i = 1; i <= n; ++ i ) {
scanf ( "%s", tmp + 1 );
for ( int j = 1; j <= n; ++ j ) {
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + ( tmp[j] == '#' );
}
}
q = rint ();
for ( int i = 1, r1, c1, r2, c2; i <= q; ++ i ) {
r1 = rint (), c1 = rint (), r2 = rint (), c2 = rint ();
qrys.push_back ( { r1, c1, r2, c2, i } );
}
solve ( qrys, 0, n + 1 >> 1 );
for ( int i = 1; i <= q; ++ i ) wint ( ans[i] ), putchar ( '\n' );
return 0;
}

最新文章

  1. Guava学习-目录
  2. jenkins 使用oclint 扫描 oc 代码
  3. objective-c(框架)
  4. SharePoint 2016 开发 工具Preview发布
  5. mysql 将时间戳直接转换成日期时间
  6. MINE
  7. javascript 中根据sort 方法随机数组 (Math.random)
  8. [ActionScript 3.0] AS3.0 获取像素点的灰度
  9. 【Backbone】简介
  10. GITLAB的版本回退(非命令行)
  11. UESTC 1425 Another LCIS
  12. SoupUI学习资料
  13. 73_leetcode_Construct Binary Tree from Inorder and Postorder Traversal
  14. GitHub上最火的74个Android开源项目
  15. Android 开发环境搭建之——ADT-Bundle for Windows
  16. HDU 5037 FROG (贪婪)
  17. Unity3d之协程自实现测试
  18. LDAP apacheds解决方案
  19. ERROR: Cannot change version of project facet Dynamic Web Module to 3.0?
  20. ledisdb:支持类redis接口的嵌入式nosql

热门文章

  1. Oracle 五种约束的创建和移除:
  2. vim安装使用pathogen
  3. 移动端字体图标不显示的Bug
  4. python极简教程04:进程和线程
  5. JAVA之G1垃圾回收器
  6. spring-data-jpa -hibernate --specificationExecutor
  7. MySQL索引失效的常见场景
  8. preg_match绕过总结
  9. Java基础-JNI入门示例
  10. 1月29日 体温APP开发记录