[luoguP2601] [ZJOI2009]对称的正方形(二维Hash + 二分 || Manacher)
很蒙蔽,不知道怎么搞。
网上看题解有说可以哈希+二分搞,也有的人说用Manacher搞,Manacher是什么鬼?以后再学。
对于这个题,可以从矩阵4个角hash一遍,然后枚举矩阵中的点,再二分半径。
但是得考虑边的长度为奇偶所带来的影响。
比如
1 1
1 1
这个边数为偶数的矩阵显然没法搞。
所以得在矩阵中插入0,
变成
0 0 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 0 1 0
0 0 0 0 0
具体操作就看代码好了。
然后只枚举 行 + 列 为偶数的点就行。
注意 用 unsigned long long 会超时和超空间,数据允许用 unsigned int
——代码
1 #include <cstdio> 2 #include <iostream> 3 #define UI unsigned int 4 5 const int MAXN = 2010, bs1 = 19260817, bs2 = 20011001; 6 int n, m, ans; 7 UI sum[4][MAXN][MAXN], base1[MAXN], base2[MAXN]; 8 9 inline int read() 10 { 11 int x = 0, f = 1; 12 char ch = getchar(); 13 for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; 14 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; 15 return x * f; 16 } 17 18 inline int min(int x, int y) 19 { 20 return x < y ? x : y; 21 } 22 23 inline bool pd(int x, int y, int l) 24 { 25 UI t, h; 26 h = sum[0][x + l - 1][y + l - 1] 27 - sum[0][x - l][y + l - 1] * base1[l + l - 1] 28 - sum[0][x + l - 1][y - l] * base2[l + l - 1] 29 + sum[0][x - l][y - l] * base1[l + l - 1] * base2[l + l - 1]; 30 t = sum[1][x + l - 1][y - l + 1] 31 - sum[1][x - l][y - l + 1] * base1[l + l - 1] 32 - sum[1][x + l - 1][y + l] * base2[l + l - 1] 33 + sum[1][x - l][y + l] * base1[l + l - 1] * base2[l + l - 1]; 34 if(h ^ t) return 0; 35 t = sum[2][x - l + 1][y + l - 1] 36 - sum[2][x + l][y + l - 1] * base1[l + l - 1] 37 - sum[2][x - l + 1][y - l] * base2[l + l - 1] 38 + sum[2][x + l][y - l] * base1[l + l - 1] * base2[l + l - 1]; 39 if(h ^ t) return 0; 40 t = sum[3][x - l + 1][y - l + 1] 41 - sum[3][x + l][y - l + 1] * base1[l + l - 1] 42 - sum[3][x - l + 1][y + l] * base2[l + l - 1] 43 + sum[3][x + l][y + l] * base1[l + l - 1] * base2[l + l - 1]; 44 if(h ^ t) return 0; 45 return 1; 46 } 47 48 inline int work(int i, int j) 49 { 50 int mid, s = 0, x = 1, y = min(min(i, n - i + 1), min(j, m - j + 1));//二分半径 51 while(x <= y) 52 { 53 mid = (x + y) >> 1; 54 if(pd(i, j, mid)) s = mid, x = mid + 1; 55 else y = mid - 1; 56 } 57 return s; 58 } 59 60 int main() 61 { 62 int i, j, k, x; 63 n = read(); 64 m = read(); 65 n = n << 1 | 1; 66 m = m << 1 | 1; 67 for(i = 2; i <= n; i += 2) 68 for(j = 2; j <= m; j += 2) 69 { 70 x = read(); 71 for(k = 0; k < 4; k++) sum[k][i][j] = x; 72 } 73 base1[0] = base2[0] = 1; 74 for(i = 1; i <= n; i++) base1[i] = base1[i - 1] * bs1; 75 for(i = 1; i <= m; i++) base2[i] = base2[i - 1] * bs2; 76 for(i = 1; i <= n; i++) 77 for(j = 1; j <= m; j++) 78 sum[0][i][j] += sum[0][i - 1][j] * bs1; 79 for(i = 1; i <= n; i++) 80 for(j = 1; j <= m; j++) 81 sum[0][i][j] += sum[0][i][j - 1] * bs2; 82 for(i = 1; i <= n; i++) 83 for(j = m; j; j--) 84 sum[1][i][j] += sum[1][i - 1][j] * bs1; 85 for(i = 1; i <= n; i++) 86 for(j = m; j; j--) 87 sum[1][i][j] += sum[1][i][j + 1] * bs2; 88 for(i = n; i; i--) 89 for(j = 1; j <= m; j++) 90 sum[2][i][j] += sum[2][i + 1][j] * bs1; 91 for(i = n; i; i--) 92 for(j = 1; j <= m; j++) 93 sum[2][i][j] += sum[2][i][j - 1] * bs2; 94 for(i = n; i; i--) 95 for(j = m; j; j--) 96 sum[3][i][j] += sum[3][i + 1][j] * bs1; 97 for(i = n; i; i--) 98 for(j = m; j; j--) 99 sum[3][i][j] += sum[3][i][j + 1] * bs2; 100 for(i = 1; i <= n; i++) 101 for(j = 1; j <= m; j++) 102 if((i ^ j ^ 1) & 1) 103 ans += work(i, j) >> 1; 104 printf("%d\n", ans); 105 return 0; 106 }
Manacher的话,学完再搞吧。