[luoguP2601] [ZJOI2009]对称的正方形(二维Hash + 二分 || Manacher)
2017-05-16 20:34
363 查看
很蒙蔽,不知道怎么搞。
网上看题解有说可以哈希+二分搞,也有的人说用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
——代码
#include <cstdio> #include <iostream> #define UI unsigned int const int MAXN = 2010, bs1 = 19260817, bs2 = 20011001; int n, m, ans; UI sum[4][MAXN][MAXN], base1[MAXN], base2[MAXN]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline int min(int x, int y) { return x < y ? x : y; } inline bool pd(int x, int y, int l) { UI t, h; h = sum[0][x + l - 1][y + l - 1] - sum[0][x - l][y + l - 1] * base1[l + l - 1] - sum[0][x + l - 1][y - l] * base2[l + l - 1] + sum[0][x - l][y - l] * base1[l + l - 1] * base2[l + l - 1]; t = sum[1][x + l - 1][y - l + 1] - sum[1][x - l][y - l + 1] * base1[l + l - 1] - sum[1][x + l - 1][y + l] * base2[l + l - 1] + sum[1][x - l][y + l] * base1[l + l - 1] * base2[l + l - 1]; if(h ^ t) return 0; t = sum[2][x - l + 1][y + l - 1] - sum[2][x + l][y + l - 1] * base1[l + l - 1] - sum[2][x - l + 1][y - l] * base2[l + l - 1] + sum[2][x + l][y - l] * base1[l + l - 1] * base2[l + l - 1]; if(h ^ t) return 0; t = sum[3][x - l + 1][y - l + 1] - sum[3][x + l][y - l + 1] * base1[l + l - 1] - sum[3][x - l + 1][y + l] * base2[l + l - 1] + sum[3][x + l][y + l] * base1[l + l - 1] * base2[l + l - 1]; if(h ^ t) return 0; return 1; } inline int work(int i, int j) { int mid, s = 0, x = 1, y = min(min(i, n - i + 1), min(j, m - j + 1));//二分半径 while(x <= y) { mid = (x + y) >> 1; if(pd(i, j, mid)) s = mid, x = mid + 1; else y = mid - 1; } return s; } int main() { int i, j, k, x; n = read(); m = read(); n = n << 1 | 1; m = m << 1 | 1; for(i = 2; i <= n; i += 2) for(j = 2; j <= m; j += 2) { x = read(); for(k = 0; k < 4; k++) sum[k][i][j] = x; } base1[0] = base2[0] = 1; for(i = 1; i <= n; i++) base1[i] = base1[i - 1] * bs1; for(i = 1; i <= m; i++) base2[i] = base2[i - 1] * bs2; for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) sum[0][i][j] += sum[0][i - 1][j] * bs1; for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) sum[0][i][j] += sum[0][i][j - 1] * bs2; for(i = 1; i <= n; i++) for(j = m; j; j--) sum[1][i][j] += sum[1][i - 1][j] * bs1; for(i = 1; i <= n; i++) for(j = m; j; j--) sum[1][i][j] += sum[1][i][j + 1] * bs2; for(i = n; i; i--) for(j = 1; j <= m; j++) sum[2][i][j] += sum[2][i + 1][j] * bs1; for(i = n; i; i--) for(j = 1; j <= m; j++) sum[2][i][j] += sum[2][i][j - 1] * bs2; for(i = n; i; i--) for(j = m; j; j--) sum[3][i][j] += sum[3][i + 1][j] * bs1; for(i = n; i; i--) for(j = m; j; j--) sum[3][i][j] += sum[3][i][j + 1] * bs2; for(i = 1; i <= n; i++) for(j = 1; j <= m; j++) if((i ^ j ^ 1) & 1) ans += work(i, j) >> 1; printf("%d\n", ans); return 0; }View Code
Manacher的话,学完再搞吧。
相关文章推荐
- bzoj1414 [ZJOI2009]对称的正方形(二分答案+二维哈希)
- BZOJ 1414 ZJOI2009 对称的正方形 Hash+二分
- bzoj 1414 && bzoj 3705: [ZJOI2009]对称的正方形(二维Hash)
- [BZOJ]1414: [ZJOI2009]对称的正方形 二分+hash
- NKOJ 2663 (ZJOI 2009)对称的正方形(Manacher)
- ZJOI 2009 对称的正方形 ST+Manacher
- ZJOI 2009 对称的正方形 RMQ+Manacher
- [BZOJ1414][ZJOI2009]对称的正方形(manacher+单调栈+二分)
- 【BZOJ1414/3705】[ZJOI2009]对称的正方形 二分+hash
- 1414: [ZJOI2009]对称的正方形 Hash+二分
- [ZJOI2009对称的正方形]ST+Manacher
- bzoj1414: [ZJOI2009]对称的正方形
- 【ZJOI 2009 Day2】对称的正方形
- bzoj1414 [ZJOI2009]对称的正方形 && bzoj3705 对称的正方形
- [除草]BZOJ 1414 [ZJOI2009]对称的正方形
- bzoj 1414: [ZJOI2009]对称的正方形
- bzoj 1414: [ZJOI2009]对称的正方形
- bzoj1414 [ZJOI2009]对称的正方形
- bzoj 1414: [ZJOI2009]对称的正方形 manacher算法+單調隊列
- [luoguP2216] [HAOI2007]理想的正方形(二维单调队列)