传送门

题目大意

找到所有的上下左右都相同的正方形。

思路:二分+二维Hash

这道题我们首先想到不能暴力判断一个正方形是否合法。

然后我们发现当一个正方形合法时,以这个正方形为中心且比它小的正方形也合法。

所以我们可以枚举每个正方形的中心点,二分求出以这个点为中心点的最大合法正方形的边长L,其贡献是 $\frac{L+1}{2}$

我们再回过来讨论如何判断一个正方形是否合法。

如果这个正方形的原来的、上下翻转的和左右翻转的矩阵都一样,那么这个正方形就是合法的。

以这个思路为出发点,我们可以用二维Hash预处理出这个正方形原来的、上下翻转的、左右反转的矩阵,每次判断的时候只要判断这三个矩阵是否相同就可以了。

在枚举中心点的时候要分类讨论奇偶情况,具体见代码。

二维Hash的求法:

先处理行,在处理列,查询和二维前缀和基本相似,但要注意二维Hash的加减有所不同。

部分代码:

  1. void init() {
  2. //一行的哈希值
  3. for(int i = 1; i <= n; i++)
  4. for(int j = 1; j <= m; j++)
  5. a[i][j] = a[i][j - 1] * B1 + _a[i][j];
  6. //一列的哈希值
  7. for(int i = 1; i <= n; i++)
  8. for(int j = 1; j <= m; j++)
  9. a[i][j] += a[i - 1][j] * B2;
  10. }
  11. //查询
  12. unsigned long long query(int x, int y, int X, int Y) {
  13. unsigned long long res = a[x][y] - a[X][Y - 1] * pow1[y - Y + 1] - a[X - 1][Y] * pow2[x - X + 1] + a[X - 1][Y - 1] * pow1[y - Y + 1] * pow2[x - X + 1];
  14. return res;
  15. }

代码

  1. #include <cstdio>
  2. #include <iostream>
  3.  
  4. #define RI register int
  5. #define mid (l + r >> 1)
  6.  
  7. using namespace std;
  8.  
  9. template <class T>
  10. inline void read(T &x) {
  11. x = 0; T f = 1; char c = getchar();
  12. while(c > '9' || c < '0') {
  13. if(c == '-')
  14. f = -f;
  15. c = getchar();
  16. }
  17. while(c >= '0' && c <= '9') {
  18. x = x * 10 + c - '0';
  19. c = getchar();
  20. }
  21. x *= f;
  22. }
  23.  
  24. typedef unsigned long long ull;
  25. const int N = 1e3 + 1;
  26. const int B1 = 233;
  27. const int B2 = 332;
  28. int n, m, ans;
  29. ull a[N][N], b[N][N], c[N][N];
  30. ull pow1[N], pow2[N];
  31.  
  32. inline void Read() {
  33. read(n), read(m);
  34. for(RI i = 1; i <= n; i++)
  35. for(RI j = 1; j <= m; j++)
  36. read(a[i][j]),
  37. b[i][m - j + 1] = a[i][j],//左右翻转
  38. c[n - i + 1][j] = a[i][j];//上下翻转
  39. }
  40. //二维哈希预处理
  41. inline void init() {
  42. for(RI i = 1; i <= n; i++)
  43. for(RI j = 1; j <= m; j++)
  44. a[i][j] += a[i][j - 1] * B1,
  45. b[i][j] += b[i][j - 1] * B1,
  46. c[i][j] += c[i][j - 1] * B1;
  47. for(RI i = 1; i <= n; i++)
  48. for(RI j = 1; j <= m; j++)
  49. a[i][j] += a[i - 1][j] * B2,
  50. b[i][j] += b[i - 1][j] * B2,
  51. c[i][j] += c[i - 1][j] * B2;
  52. pow1[0] = pow2[0] = 1;
  53. for(RI i = 1, tmp = max(n, m); i <= tmp; i++)
  54. pow1[i] = pow1[i - 1] * B1,
  55. pow2[i] = pow2[i - 1] * B2;
  56. }
  57. //判断三个矩阵是否相同
  58. inline bool check(int x, int y, int le) {
  59. //因为会自然溢出的缘故,unsigned 没有小于0的时候 所以不能写x-le<0 (细节
  60. if(x > n || y > m || x < le || y < le)
  61. return false;
  62. ull res1 = a[x][y] - a[x][y - le] * pow1[le] - a[x - le][y] * pow2[le] + a[x - le][y - le] * pow1[le] * pow2[le];
  63. int tmp = y;
  64. y = m - (y - le);//位置要调整(细节
  65. ull res2 = b[x][y] - b[x][y - le] * pow1[le] - b[x - le][y] * pow2[le] + b[x - le][y - le] * pow1[le] * pow2[le];
  66. y = tmp, x = n - (x - le);//位置要调整(细节
  67. ull res3 = c[x][y] - c[x][y - le] * pow1[le] - c[x - le][y] * pow2[le] + c[x - le][y - le] * pow1[le] * pow2[le];
  68. return res1 == res2 && res2 == res3;
  69. }
  70. inline void solve() {
  71. int tmp = min(n, m);
  72. //这里要分两点讨论,边长为偶数的是枚举格点,而边长为奇数的则是枚举格子(细节
  73. for(RI i = 0; i < n; i++)
  74. for(RI j = 0; j < m; j++) {
  75. int l = 1, r = tmp, res = 0;
  76. while(l < r) {
  77. if(check(i + mid, j + mid, mid + mid))
  78. res = mid, l = mid + 1;
  79. else
  80. r = mid;
  81. }
  82. ans += res;
  83. }
  84. for(RI i = 0; i < n; i++)
  85. for(RI j = 0; j < m; j++) {
  86. int l = 1, r = tmp, res = 0;
  87. while(l < r) {
  88. if(check(i + mid, j + mid, mid + mid + 1))
  89. res = mid, l = mid + 1;
  90. else
  91. r = mid;
  92. }
  93. ans += res;
  94. }
  95. ans += n * m; //1格的也算对称正方形,不要漏了(细节
  96. printf("%d\n", ans);
  97. }
  98.  
  99. int main() {
  100. Read();
  101. init();
  102. solve();
  103. return 0;
  104. }

题解-------[ZJOI2009]对称的正方形的更多相关文章

  1. 【BZOJ1414】[ZJOI2009]对称的正方形(哈希)

    [BZOJ1414][ZJOI2009]对称的正方形(哈希) 题面 BZOJ 洛谷 题解 深思熟虑一波,发现一个矩阵如果左右对称的话,那么它每行都是一个回文串,同理,如果上下对称的话,那么每列都是一个 ...

  2. 【BZOJ1414/3705】[ZJOI2009]对称的正方形 二分+hash

    [BZOJ1414/3705][ZJOI2009]对称的正方形 Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们 ...

  3. bzoj 1414: [ZJOI2009]对称的正方形 manacher算法+單調隊列

    1414: [ZJOI2009]对称的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 331  Solved: 149[Submit][Stat ...

  4. bzoj 1414: [ZJOI2009]对称的正方形

    Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...

  5. [luoguP2601] [ZJOI2009]对称的正方形(二维Hash + 二分 || Manacher)

    传送门 很蒙蔽,不知道怎么搞. 网上看题解有说可以哈希+二分搞,也有的人说用Manacher搞,Manacher是什么鬼?以后再学. 对于这个题,可以从矩阵4个角hash一遍,然后枚举矩阵中的点,再二 ...

  6. luoguP2601 对称的正方形

    题目描述 给出一个数字矩形,求这个矩形中有多少个子正方形满足上下对称.左右对称. 思路 我们可以用3个哈希数组 \(a\ b\ c\) 分别表示矩形从左上往右下看,从左下往右上看,从右上往左下看的样子 ...

  7. 【bzoj 1414】对称的正方形 单调队列+manacher

    Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...

  8. 题解 P1387 【最大正方形】

    传送门 搞不清楚为什么这一题要DP . . . . . . 思路: \(n\le100\),考虑暴力. 要求一大块区间内都是1,考虑前缀和. 在矩阵中求一个符合条件的子矩阵,考虑\(n^3\)的&qu ...

  9. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

随机推荐

  1. DuplicateHandle伪句柄与实句柄的应用二

    //扫描进程列表,获得进程名为 ConsoleApplication2.exe的进程句柄B,把当前进程A的伪 //句柄传递给B,在B进程中关闭它 #include "stdafx.h&quo ...

  2. Vue点击按钮下载对应图片

    最近有用到点击某个按钮 自动下载对应图片,可是对于浏览器不同的问题,会有‘个别’浏览器出现不能下载的或者下载的效果不同等的问题, 可以直接用创建canvas方法: 定义图片地址Img: "w ...

  3. 19 01 15 js 尺寸相关 滚动事件

    尺寸相关.滚动事件 1.获取和设置元素的尺寸 width().height() 获取元素width和height innerWidth().innerHeight() 包括padding的width和 ...

  4. 了解OOM

    1)什么是OOM? OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,来源于java.lang.OutOfMemoryError.看下关于的官方说明: Thrown when ...

  5. cf1208 D Restore Permutation (二分+树状数组)

    题意 让你构造一个长度为n的序列,记为p1……pn,(这个序列是1~n的全排列的一种) 给你n个数,记为s1……sn,si的值为p1……pi-1中小于pi的数的和. 思路 显然,应该倒着来,也就是从p ...

  6. python3 sort list

    1. 对元素指定的某一部分进行排序,关键字排序 s = ['release.10.txt','release.1.txt','release.2.txt','release.14.txt','rele ...

  7. HashMap源码阅读笔记

    HashMap源码阅读笔记 本文在此博客的内容上进行了部分修改,旨在加深笔者对HashMap的理解,暂不讨论红黑树相关逻辑 概述   HashMap作为经常使用到的类,大多时候都是只知道大概原理,比如 ...

  8. sort()函数使用详解

    使用时需要导入头文件<algorithm> #include<algorithm> 语法描述:sort(begin,end,cmp),cmp参数可以没有,如果没有默认非降序排序 ...

  9. mysql经典查询语句-笔记

    笔记来源公开课,谢谢! 1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name ...

  10. Win10 MySQL5.7中文乱码问题

    https://blog.csdn.net/hh___56789/article/details/87900923 最好把 utf8 都换成utf8mb4 ,以免以后遇到意想不到的错误.utf8有漏洞 ...