luoguP2601 对称的正方形
题目描述
给出一个数字矩形,求这个矩形中有多少个子正方形满足上下对称、左右对称。
思路
我们可以用3个哈希数组 \(a\ b\ c\) 分别表示矩形从左上往右下看,从左下往右上看,从右上往左下看的样子,那么我们可以得到:
- 如果正方形 \((x,y,u,v)\)(即以 \((x,y)\) 这一格为左上角,\((u,v)\) 为右下角的正方形)左右对称,那么它从左上往右下看和从右上往左下看是一样的,即 \(a\) 哈希数组和 \(c\) 哈希数组相等。
- 如果正方形 \((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 对称的正方形的更多相关文章
- bzoj 1414: [ZJOI2009]对称的正方形 manacher算法+單調隊列
1414: [ZJOI2009]对称的正方形 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 331 Solved: 149[Submit][Stat ...
- 【BZOJ1414】[ZJOI2009]对称的正方形(哈希)
[BZOJ1414][ZJOI2009]对称的正方形(哈希) 题面 BZOJ 洛谷 题解 深思熟虑一波,发现一个矩阵如果左右对称的话,那么它每行都是一个回文串,同理,如果上下对称的话,那么每列都是一个 ...
- 【BZOJ1414/3705】[ZJOI2009]对称的正方形 二分+hash
[BZOJ1414/3705][ZJOI2009]对称的正方形 Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们 ...
- [luoguP2601] [ZJOI2009]对称的正方形(二维Hash + 二分 || Manacher)
传送门 很蒙蔽,不知道怎么搞. 网上看题解有说可以哈希+二分搞,也有的人说用Manacher搞,Manacher是什么鬼?以后再学. 对于这个题,可以从矩阵4个角hash一遍,然后枚举矩阵中的点,再二 ...
- 【bzoj 1414】对称的正方形 单调队列+manacher
Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...
- bzoj 1414: [ZJOI2009]对称的正方形
Description Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究.最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵.通过观察,Orez发现这些数据蕴涵了一 ...
- 题解-------[ZJOI2009]对称的正方形
传送门 题目大意 找到所有的上下左右都相同的正方形. 思路:二分+二维Hash 这道题我们首先想到不能暴力判断一个正方形是否合法. 然后我们发现当一个正方形合法时,以这个正方形为中心且比它小的正方形也 ...
- hdu4618 Palindrome Sub-Array dp+记忆化搜索 或者直接暴力
题意就是找一个 左右上下对称的正方形矩阵. 连接:http://acm.hdu.edu.cn/showproblem.php?pid=4618 没想到记忆+dp和暴力就能水过... //记忆话搜索+d ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
随机推荐
- 多线程笔记-CancellationToken(取消令牌)
介绍 为什么需要CancellationToken?因为Task没有方法支持在外部取消Task,只能通过一个公共变量存放线程的取消状态,在线程内部通过变量判断线程是否被取消,当Cancella ...
- QT从入门到入土(三)——信号和槽机制
摘要 信号槽是 Qt 框架引以为豪的机制之一.所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号 (signal).这种发出是没有目的的,类似广播 ...
- 配置Mac 终端高亮
mac下所有vim的配色方案的样式. 下面讲解如何设置这些好看的配色 首先:在终端输入 vim ~/.bash_profile 查看是否有上面提到的某些配色,所有配色均是以.vim结束的,果有的话,再 ...
- JAVA入门基础及流程控制
JAVA入门基础及流程控制 数据类型 位 存储单位 eg:0001 0011 八位 字节 byte 处理数据单位 一字节等于八位 eg:1b=0011 0001 类变量: static int num ...
- Java 加载、操作和保存WPS文字文档
本文通过Java程序代码来展示如何来加载.操作及保存WPS格式的文字文档. 一.基本步骤:加载时,通过流加载WPS文字文档,完成相关文字操作后,再将结果文档保存到流,将流写入WPS文档,闭关闭流. 二 ...
- 【知识详解】Https详解
Https详解 1.什么是Https Http + SSL = Https 一句话说:Https是身披SSL的Http,当使用了SSL后,Http先和SSL通信,再由SSL和TCP通信, 2.为什么需 ...
- sqldbx配置连接Oracle 12C数据库
本地开发环境: Windows10 64位.Oracle 12C客户端 32位.sqlDBX (32位) =============================================== ...
- 使用JavaMailSender 发送邮件
使用JavaMailSender 发送邮件 package com.juvenxu.mvnbook.account.email; import javax.mail.MessagingExceptio ...
- Jmeter关联详解
关联的概念 从上一步操作中获取需要的值,传递给下一步操作中进行引用,形成自动关联,而不是 每次操作都去手动修改关联的值.常见的场景有SessionID.Session Token值的获取. 正则表达式 ...
- SQL SERVER Date列和Time列合并成一列处理报表数据
问题原由: intouch项目中,利用intouch脚本来存储数据时,存入的时间格式为:date,time分开存储.在报表需求中,有需要利用查询两个时间段之间的数据. 问题解决: 1.直接写脚本(写出 ...