题目描述

给出一个数字矩形,求这个矩形中有多少个子正方形满足上下对称、左右对称。

思路

我们可以用3个哈希数组 \(a\ b\ c\) 分别表示矩形从左上往右下看,从左下往右上看,从右上往左下看的样子,那么我们可以得到:

  1. 如果正方形 \((x,y,u,v)\)(即以 \((x,y)\) 这一格为左上角,\((u,v)\) 为右下角的正方形)左右对称,那么它从左上往右下看和从右上往左下看是一样的,即 \(a\) 哈希数组和 \(c\) 哈希数组相等。
  2. 如果正方形 \((x,y,u,v)\) 上下对称,那么它从左上往右下看和从左下往右上看是一样的,即 \(a\) 哈希数组和 \(b\) 哈希数组相等。

如果两条条件都满足,那么这个正方形就是对称的正方形。

我们可以分边有奇数个节点和边有偶数个节点的正方形枚举它的中心点,显然,答案是具有单调性的,于是我们就可以进行二分答案求值。

实现

我们通过处理出 \((1,1,i,j)\) 矩形的哈希值,那么就可以通过类似前缀和的方式来分别得到正方形 \((x,y,u,v)\) 的 \(a\ b\ c\) 三个值。柿子如下:

q.a=a[u][v]-a[u][y-1]*p1[v-y+1]-a[x-1][v]*p2[u-x+1]+a[x-1][y-1]*p1[v-y+1]*p2[u-x+1];
q.b=b[x][v]-b[x][y-1]*p1[v-y+1]-b[u+1][v]*p2[u-x+1]+b[u+1][y-1]*p1[v-y+1]*p2[u-x+1];
q.c=c[u][y]-c[u][v+1]*p1[v-y+1]-c[x-1][y]*p2[u-x+1]+c[x-1][v+1]*p1[v-y+1]*p2[u-x+1];

然后进行判断即可。

Code

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef unsigned long long ull;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=1e3+10;
int n,m,num[N][N],tot;ull a[N][N],b[N][N],c[N][N],p1[N],p2[N];
struct node{ull a,b,c;}q;
inline void get(int x,int y,int u,int v){
q.a=a[u][v]-a[u][y-1]*p1[v-y+1]-a[x-1][v]*p2[u-x+1]+a[x-1][y-1]*p1[v-y+1]*p2[u-x+1];
q.b=b[x][v]-b[x][y-1]*p1[v-y+1]-b[u+1][v]*p2[u-x+1]+b[u+1][y-1]*p1[v-y+1]*p2[u-x+1];
q.c=c[u][y]-c[u][v+1]*p1[v-y+1]-c[x-1][y]*p2[u-x+1]+c[x-1][v+1]*p1[v-y+1]*p2[u-x+1];
}
inline short main(){
p1[0]=p2[0]=1;
n=read(),m=read();
F(i,1,N-10)p1[i]=p1[i-1]*131,p2[i]=p2[i-1]*13331;
F(i,1,n)F(j,1,m)num[i][j]=read();
//求哈希值
F(i,1,n)F(j,1,m)a[i][j]=a[i][j-1]*131+a[i-1][j]*13331-a[i-1][j-1]*131*13331+num[i][j];
D(i,n,1)F(j,1,m)b[i][j]=b[i][j-1]*131+b[i+1][j]*13331-b[i+1][j-1]*131*13331+num[i][j];
F(i,1,n)D(j,m,1)c[i][j]=c[i][j+1]*131+c[i-1][j]*13331-c[i-1][j+1]*131*13331+num[i][j];
//偶数边长
F(i,1,n-1){
F(j,1,m-1){
int l=1,r=min(min(n-i,i),min(j,m-j)),ans=0;
while(l<=r){
int mid=(l+r)>>1;
get(i-mid+1,j-mid+1,i+mid,j+mid);
if(q.a==q.b&&q.a==q.c)l=mid+1,ans=mid;
else r=mid-1;
}tot+=ans;
}
}
//奇数边长
F(i,1,n){
F(j,1,m){
int l=1,r=min(min(n-i+1,i),min(m-j+1,j)),ans=0;
while(l<=r){
int mid=(l+r)>>1;
get(i-mid+1,j-mid+1,i+mid-1,j+mid-1);
if(q.a==q.b&&q.a==q.c)l=mid+1,ans=mid;
else r=mid-1;
}tot+=ans;
}
}
pi(tot);
return 0;
}
}
signed main(){return EMT::main();}

luoguP2601 对称的正方形的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. 题解-------[ZJOI2009]对称的正方形

    传送门 题目大意 找到所有的上下左右都相同的正方形. 思路:二分+二维Hash 这道题我们首先想到不能暴力判断一个正方形是否合法. 然后我们发现当一个正方形合法时,以这个正方形为中心且比它小的正方形也 ...

  8. hdu4618 Palindrome Sub-Array dp+记忆化搜索 或者直接暴力

    题意就是找一个 左右上下对称的正方形矩阵. 连接:http://acm.hdu.edu.cn/showproblem.php?pid=4618 没想到记忆+dp和暴力就能水过... //记忆话搜索+d ...

  9. bzoj AC倒序

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

随机推荐

  1. 如何用jmeter监控内存,CPU(1)

    要jmeter的运行环境配置好就可以: 打开这个小工具的步骤很简单,如果你已经配置好了Jmeter运行的环境,那么你也就不用去做其他的配置,直接 点击:开始-->运行-->输入cmd--& ...

  2. ESP32智能配网笔记

    基于ESP-IDF4.1 #include <string.h> #include <stdlib.h> #include "freertos/FreeRTOS.h& ...

  3. Quzrtz.net 示例

    //框架.Net Core 2.0//先用Nuget 安装最新quartz.net using System; using Quartz; using Quartz.Impl; using Syste ...

  4. 教你 PXE高效批量网络装机

    PXE高效批量网络装机一.PXE概述① PXE (Preboot eXcution Environment)② PXE批量部署的优点③ 服务端④ 客户端二.部署PXE远程安装服务搭建PXE远程安装服务 ...

  5. 【LeetCode】111. 二叉树的最小深度

    111. 二叉树的最小深度 知识点:二叉树,递归 题目描述 给定一个二叉树,找出其最小深度. 最小深度是从根节点到最近叶子节点的最短路径上的节点数量. 说明:叶子节点是指没有子节点的节点. 示例 输入 ...

  6. debug:am、cmd命令源码分析

    debug:am.cmd命令源码分析 目录 debug:am.cmd命令源码分析 am命令的实现 手机里的am am.jar cmd命令的实现 手机里的cmd cmd activity cmd.cpp ...

  7. 【Uva11400 Lighting System Design】动态规划

    分析 先按照电压从小到大排序,做一下前缀和s[i]求i之前的电灯泡的数量. 状态:$ F_i\(表示到\) i$个灯泡的最小开销. 状态转移方程:$ F_i=F_j+(s[i]-s[j])\times ...

  8. UIAutomator2 之 计算机积极拒绝

    启动 问题: Failed to establish a new connection 由于目标计算机积极拒绝,无法连接 原因: 电脑重启被IE主动开了本地代理 解决: 网络设置-关闭手动代理

  9. Querydsl与SpringBoot集成

    Querydsl为大多数数据库提供了一种基于Java的类型安全,类SQL的查询方式.相比JPA,Querydsl能提供更加强大的查询方式,比如关联查询.相比MyBatis,Querydsl省去了XML ...

  10. Verilog定点数计算

    https://blog.csdn.net/maxwell2ic/article/details/80620991 https://blog.csdn.net/mdpsdhr/article/deta ...