Description

Orez很喜欢搜集一些神秘的数据,并经常把它们排成一个矩阵进行研究。最近,Orez又得到了一些数据,并已经把它们排成了一个n行m列的矩阵。通过观察,Orez发现这些数据蕴涵了一个奇特的数,就是矩阵中上下对称且左右对称的正方形子矩阵的个数。 Orez自然很想知道这个数是多少,可是矩阵太大,无法去数。只能请你编个程序来计算出这个数。

Input

文件的第一行为两个整数n和m。接下来n行每行包含m个正整数,表示Orez得到的矩阵。

Output

文件中仅包含一个整数answer,表示矩阵中有answer个上下左右对称的正方形子矩阵。

Sample Input

5 5
4 2 4 4 4
3 1 4 4 3
3 5 3 3 3
3 1 5 3 3
4 2 1 2 4

Sample Output

27

数据范围
对于30%的数据 n,m≤100
对于100%的数据 n,m≤1000 ,矩阵中的数的大小≤109

题解:

  蒟蒻写了4h……(本来是想怂,但看到人家说gang了一晚上,然后默默关了网页自己去作了),还有,膜bzoj 1414榜上900B+400MS大佬。

   首先用manacher,双倍复制原数组,跑出$P_{0,i,j},P_{1,i,j}$,分别表示第i行j列的横着的和竖着的回文半径。

  显然只要求出每个位置的最大正方形边长答案就出来了。

  我们以每个位置$(i,j)$为坐标轴原点,显然,我们只要得到x,y轴上的回文半径即可。先讨论x非负轴。同时,对于每个位置我们可以观察发现,在x轴上的位置,应该满足其$x-p[1][i][x]+1<=j$。然后发现对于$(i,j+1)$是可以继承满足$(i,j)$的一部分点,而不能继承的只有$(i,j)$在x轴对应点,同时我们可能会有一部分新点加入$(i,j+1)$的集合点。(⊙v⊙)嗯,这不就是队列的时间关系嘛。

  然后怎么选取$(i,j)$所能得到的此时尽可能最大值边长呢。我们可以画个图,观察发现,我们在$(i,j)$点集的选取,只和最小值有关,所以当出现第一个不满足$x-p_{1,i,x}+1<=j$的点就没必要再在非负半轴上往后扫了。

  证明的话倒是挺简单的,就不多说了。

  以上一结合就得到了我们需要的数据结构,单调队列。

  那么对于x非正半轴以及y轴的情况也与x非负半轴的情况相同。时间复杂度$O(n^{2})$

  最后答案累加每个$(i,j)$奇偶性相同的位置即可。

Ps:可能是我打得蠢……都跑不过带$log$的……

代码:

  

 #include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
inline int read(){
int s=;char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') s=s*+(ch^),ch=getchar();
return s;
}
int n,m;
int Mar[][];
int p[][][];
inline void manacher(){
for(int i=;i<=*n+;i++){
int pos,mar=;
for(int j=;j<=*m+;j++){
if(mar>j) p[][i][j]=min(p[][i][pos*-j],mar-j-);
else p[][i][j]=;
while(Mar[i][j-p[][i][j]]==Mar[i][j+p[][i][j]]) p[][i][j]++;
if(mar<j+p[][i][j]-)
mar=j+p[][i][j]-,pos=j;
}
}
for(int i=;i<=*m+;i++){
int pos,mar=;
for(int j=;j<=*n+;j++){
if(mar>j) p[][i][j]=min(p[][i][pos*-j],mar-j-);
else p[][i][j]=;
while(Mar[j-p[][i][j]][i]==Mar[j+p[][i][j]][i]) p[][i][j]++;
if(mar<j+p[][i][j]-)
mar=j+p[][i][j]-,pos=j;
}
}
}
int que[],l,r;
int re[][];
int main(){
n=read(),m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
Mar[i<<][j<<]=read();
for(int i=;i<=*n+;i++)
Mar[i][]=-,Mar[i][m+<<]=-;
for(int i=;i<=*m+;i++)
Mar[][i]=-,Mar[n+<<][i]=-;
manacher();
for(int i=;i<=*n;i++){
l=,r=;
for(int j=((i^)&)+,k=;j<=*m+;j+=){
while(k<=*m+&&k-p[][k][i]+<=j){
while(l<=r&&p[][que[r]][i]>=p[][k][i])
r--;
que[++r]=k;
k++;
}
while(l<=r&&que[l]<j)
l++;
re[i][j]=min(que[r]-j+,p[][que[l]][i]);
}
l=,r=;
for(int j=*m+-((i^)&),k=*m+;j>=;j-=){
while(k&&k+p[][k][i]->=j){
while(l<=r&&p[][que[r]][i]>=p[][k][i])
r--;
que[++r]=k--;
}
while(l<=r&&que[l]>j)
l++;
re[i][j]=min(min(j-que[r]+,p[][que[l]][i]),re[i][j]);
} }
for(int i=;i<=*m;i++){
l=,r=;
for(int j=+((i^)&),k=;j<=*n+;j+=){
while(k<=*n+&&k-p[][k][i]+<=j){
while(l<=r&&p[][que[r]][i]>=p[][k][i])
r--;
que[++r]=k;
k++;
}
while(l<=r&&que[l]<j)
l++;
re[j][i]=min(min(que[r]-j+,p[][que[l]][i]),re[j][i]);
}
l=,r=;
for(int j=*n+-((i^)&),k=*n+;j;j--){
while(k&&k+p[][k][i]->=j){
while(l<=r&&p[][que[r]][i]>=p[][k][i])
r--;
que[++r]=k--;
}
while(l<=r&&que[l]>j)
l++;
re[j][i]=min(min(j-que[r]+,p[][que[l]][i]),re[j][i]);
}
}
int ans=;
for(int i=;i<=*n;i++){
for(int j=((i^)&)+;j<=*m+;j+=)
if((i&)==(j&))
ans+=re[i][j]>>;
}
printf("%d",ans);
}

【bzoj 1414】对称的正方形 单调队列+manacher的更多相关文章

  1. BZOJ 1047 理想的正方形(单调队列)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1047 题意:给出一个n*m的矩阵.在所有K*K的子矩阵中,最大最小差值最小的是多少? 思 ...

  2. bzoj 1047 : [HAOI2007]理想的正方形 单调队列dp

    题目链接 1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2369  Solved: 1266[Submi ...

  3. BZOJ 1047: [HAOI2007]理想的正方形( 单调队列 )

    单调队列..先对每一行扫一次维护以每个点(x, y)为结尾的长度为n的最大最小值.然后再对每一列扫一次, 在之前的基础上维护(x, y)为结尾的长度为n的最大最小值. 时间复杂度O(ab) (话说还是 ...

  4. BZOJ 1047: [HAOI2007]理想的正方形 单调队列瞎搞

    题意很简明吧? 枚举的矩形下边界和右端点即右下角,来确定矩形位置: 每一个纵列开一个单调队列,记录从 i-n+1 行到 i 行每列的最大值和最小值,矩形下边界向下推移的时候维护一下: 然后在记录的每一 ...

  5. BZOJ1047: [HAOI2007]理想的正方形 [单调队列]

    1047: [HAOI2007]理想的正方形 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2857  Solved: 1560[Submit][St ...

  6. BZOJ 1499 [NOI2005] 瑰丽华尔兹 | 单调队列优化DP

    BZOJ 1499 瑰丽华尔兹 | 单调队列优化DP 题意 有一块\(n \times m\)的矩形地面,上面有一些障碍(用'#'表示),其余的是空地(用'.'表示).每时每刻,地面都会向某个方向倾斜 ...

  7. P2216 [HAOI2007]理想的正方形 (单调队列)

    题目链接:P2216 [HAOI2007]理想的正方形 题目描述 有一个 \(a\times b\)的整数组成的矩阵,现请你从中找出一个 \(n\times n\)的正方形区域,使得该区域所有数中的最 ...

  8. bzoj 3831 Little Bird (单调队列优化dp)

    /*先贴个n*n的*/ #include<iostream> #include<cstdio> #include<cstring> #define maxn 100 ...

  9. BZOJ 1499 NOI2005 瑰丽华尔兹 单调队列

    题目大意:给定一个m*n的地图,一些点有障碍物,钢琴初始在一个点,每一个时间段能够选择向给定的方向移动一段距离,求最长路径长 朴素DP的话,我们有T个时间段,每一个时间段有m*n个点,n个时间,一定会 ...

随机推荐

  1. Mongodb3.6 快速入门(一)

    一.安装 官网下载地址 文章中用的3.6community server 64 位. 安装完成后的目录如下: 二.启动Mongodb 有多种方式可以启动Mongodb,但在实际项目中,主要还是通过配置 ...

  2. 详解Lambda

    定义好委托: public delegate int FirDelegate(int a); public delegate int SecDelegate(int a,int b); public ...

  3. Netty入门

    一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...

  4. AngularJs 学习笔记(四)服务

    模型是指$scope上保存的包含瞬时状态数据的JavaScript对象. 服务是一个单例对象,只会被$injector实例化一次,并且是在需要的时候才会被创建,服务提供了把与特定功能相关联的方法集中在 ...

  5. AdminIII连接linux Postgresql过程中的几个小问题

    1.postgresql.conf主配置文件中要配置postgresql绑定的IP,如果不设置,可能只绑定本地闭环地址:127.0.0.1,可以设定为0.0.0.0:就包括了一切IPv4地址 2.pg ...

  6. Tomcat中常见线程说明

    http://blog.csdn.NET/jeff_fangji/article/details/41786205 本文讲述了Tomcat的常见线程的功能.名称.线程池和配置等信息,其中源码来自于To ...

  7. (七):C++分布式实时应用框架 2.0

    C++分布式实时应用框架 2.0 技术交流合作QQ群:436466587 欢迎讨论交流 上一篇:(六):大型项目容器化改造 版权声明:本文版权及所用技术归属smartguys团队所有,对于抄袭,非经同 ...

  8. HTML知识点总结

    HTML知识点总结 一.需要熟悉的基本快捷键 ctrl+c            复制 ctrl+v            粘贴 ctrl+x            剪切 ctrl+tab       ...

  9. 连接到放置本地yum源服务器之前的注意事项

    1.确认系统防火墙关闭 2.启动httpd服务 service httpd start 如果提示没有httpd服务: 安装httpd服务 yum install -y httpd 作者:Daley Z ...

  10. Hibernate Session总结

    现在我们可以在 IDEA 下新建一个 Hibernate 项目,接着上次内容这次主要总结一下 Hibernate 的 Session,及其核心方法. Session 概述 Session 接口是 Hi ...