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 ...
随机推荐
- 使用Hugo框架搭建博客的过程 - 功能拓展
前言 本文介绍一些拓展功能,如文章页面功能增加二级菜单,相关文章推荐和赞赏.另外,使用脚本会大大简化写作后的上传流程. 文章页面功能 这部分功能的拓展主要是用前端的JS和CSS,如果对前端不了解,可以 ...
- 两个有序数组合并为一个有序数组---python
def merge(a, b): """ 合并2个有序数组,默认a,b都是从小到大的有序数组 """ # 1.临时变量 i, j = 0, ...
- WPF教程一:创建Hello world来理解XAML的内容及编译
在实际的WPF开发中遇到很多再用Winform写法来写WPF的开发人员,很多时候项目进度延期.出现非必要的BUG等等.大多是因为开发人员虽然是再写WPF. 但是没有好好的学过WPF,就导致无法发挥出W ...
- viewport深入理解和使用
什么是viewport ? viewport是用户网页的可视区域,也可叫做视区.手机浏览器是把页面放在一个虚拟的窗口(viewport)中,通常这个虚拟的窗口比屏幕宽,这样就不用把网页挤到很小的窗口中 ...
- [善用佳软]Chrome插件之彩云小译
最近公众号新推出个栏目[善用佳软],旨在和大家分享各种小插件和制作开源小软件. 最近在浏览外网时,发现一个贼好用的翻译神器---[彩云小译],在网页端就可以快速的对照翻译出来,经过试用发现无论是速度还 ...
- ArcGis Server安装与使用
ArcGis Server安装 下载ArcGisServer 双击Setup.exe,然后一直下一步. 安装完成后,点击完成,弹出如下界面: 选择第三个选项,然选择[.ecp]后缀名的授权文件. 然后 ...
- php使用curl模拟post请求
废话不多说,直接上代码,做个笔记. $url="http://localhost/header_server.php"; $body = array("mobile&qu ...
- 网络损伤仪WANsim中的乱序功能
乱序 乱序功能需要指定每个帧 发生乱序的概率,以及新的帧的位置相较于原来位置的时间范围. 乱序的概率范围是0%~20%,颗粒度是0.001%.Delay的设置范围为 0s~10s,颗粒度为0.1 ms ...
- odoo14里面给下载PDF附件加水印
依赖包:pip install reportlab Odoo 中附件的下载会经过 ir.http 的 def binary_content() 方法获取附件内容等必要信息, 所以我们需要继承 ir.h ...
- javascript学习--(四)面向对象:
一.生成器generator: javascript里的generator函数是用function*定义的, 案例:yield 也会返回 function* foo(x){ yield x+1; yi ...