zoukankan      html  css  js  c++  java
  • [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
    ", ans);
    105     return 0;
    106 }
    View Code

    Manacher的话,学完再搞吧。

  • 相关阅读:
    Lambda表达式
    java中解决小数精度问题
    [Unity]-黑魂复刻-动画 001
    kuka Virtual Remote pendant 连接使用
    C# 操作 pg 数据库
    C#常用字符串操作
    Go学习笔记之相关资源
    Go学习笔记之常用命令
    Go学习笔记之安装
    nginx学习笔记之安装
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/6863532.html
Copyright © 2011-2022 走看看