您的位置:首页 > 其它

[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的话,学完再搞吧。

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: