Codeforces Round #619 (Div. 2) E. Nanosoft 最大合法正方形

阳光穿透心脏的1/2处 2023-07-15 13:25 15阅读 0赞

题目链接:http://codeforces.com/contest/1301/problem/E
题意:对于一个正方形分成4等份,左上角红,右上角绿,左下角黄,右下角蓝才认为合法的,对于
给定的矩形,询问你这个矩形中最大的合法正方形面积
思路:用二维前缀和统计方块,正方形边长最大250,枚举边长,每次检查左上角个数是否为l*l,
其余角同样,做个前缀和可以O(1)判断

如果范围再大些我们可以用考虑二分+二维ST表,因为每个大的合法正方形必然包含一个小的合法正方形,满足单调性

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. #define fi first
  5. #define se second
  6. #define ls rt << 1
  7. #define rs rt << 1|1
  8. #define lson l, mid, ls
  9. #define rson mid + 1, r, rs
  10. #define pll pair<ll, ll>
  11. #define pii pair<int, int>
  12. #define ull unsigned long long
  13. #define pdd pair<double, double>
  14. const int mod = 1e9 + 7;
  15. const int maxn = 3e5 + 10;
  16. const int inf = 0x3f3f3f3f;
  17. int cnt[5][505][505], r1[maxn], c1[maxn], r2[maxn], c2[maxn], ans[maxn];
  18. char s[505][505];
  19. int n, m, q;
  20. int check(int k, int x1, int y1, int x2, int y2)
  21. {
  22. return cnt[k][x2][y2] - cnt[k][x1 - 1][y2] - cnt[k][x2][y1 - 1] + cnt[k][x1 - 1][y1 - 1];
  23. }
  24. int main()
  25. {
  26. scanf("%d%d%d", &n, &m, &q);
  27. for(int i = 1; i <= n; ++i)
  28. {
  29. scanf("%s", s[i] + 1);
  30. for(int j = 1; j <= m; ++j)
  31. {
  32. if(s[i][j] == 'R') cnt[0][i][j] = 1;
  33. if(s[i][j] == 'G') cnt[1][i][j] = 1;
  34. if(s[i][j] == 'Y') cnt[2][i][j] = 1;
  35. if(s[i][j] == 'B') cnt[3][i][j] = 1;
  36. }
  37. }
  38. for(int k = 0; k <= 3; ++k)
  39. {
  40. for(int i = 1; i <= n; ++i) //前缀和
  41. for(int j = 1; j <= m; ++j)
  42. cnt[k][i][j] += cnt[k][i - 1][j];
  43. for(int i = 1; i <= n; ++i)
  44. for(int j = 1; j <= m; ++j)
  45. cnt[k][i][j] += cnt[k][i][j - 1];
  46. }
  47. for(int i = 1; i <= q; ++i) scanf("%d%d%d%d", &r1[i], &c1[i], &r2[i], &c2[i]);
  48. for(int l = 1; l <= 250; ++l)
  49. {
  50. if(2 * l > n || 2 * l > m) break;
  51. for(int i = 1; i <= n; ++i)
  52. for(int j = 1; j <= m; ++j)
  53. cnt[4][i][j] = 0;
  54. for(int i = 1; i <= n - 2 * l + 1; ++i) //判断是否存在合法正方形
  55. {
  56. for(int j = 1; j <= m - 2 * l + 1; ++j)
  57. {
  58. if(check(0, i, j, i + l - 1, j + l - 1) == l * l && check(1, i, j + l, i + l - 1, j + 2 * l - 1) == l * l)
  59. {
  60. if(check(2, i + l, j , i + 2 * l - 1, j + l - 1) == l * l && check(3, i + l, j + l, i + 2 * l - 1, j + 2 * l - 1) == l * l)
  61. cnt[4][i][j] = 1;
  62. }
  63. }
  64. }
  65. for(int i = 1; i <= n - 2 * l + 1; ++i) //前缀和
  66. for(int j = 1; j <= m - 2 * l + 1; ++j)
  67. cnt[4][i][j] += cnt[4][i - 1][j];
  68. for(int i = 1; i <= n - 2 * l + 1; ++i)
  69. for(int j = 1; j <= m - 2 * l + 1; ++j)
  70. cnt[4][i][j] += cnt[4][i][j - 1];
  71. for(int i = 1; i <= q; ++i)
  72. {
  73. if(r2[i] - r1[i] + 1 >= 2 * l && c2[i] - c1[i] + 1 >= 2 * l && check(4, r1[i], c1[i], r2[i] - 2 * l + 1, c2[i] - 2 * l + 1) > 0)
  74. ans[i] = l;
  75. }
  76. }
  77. for(int i = 1; i <= q; ++i)
  78. printf("%d\n", 4 * ans[i] * ans[i]);
  79. return 0;
  80. }

发表评论

表情:
评论列表 (有 0 条评论,15人围观)

还没有评论,来说两句吧...

相关阅读