1414: [ZJOI2009]对称的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 331  Solved: 149
[Submit][Status]

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

 
 
  現在我確實是遇到難一點的題套單調隊列就搞不清楚,這道題看了以後很容易想到計算每個點向兩個方向延展的迴文串最長長度,然而如何快速統計卻是個問題,邊長2a的目標正方形滿足其行上連續a的範圍內的格子列方向延展長度大於a,且a小於中心橫向迴文串延展長度。(說的我都暈了),解決這個問題,我用的是單調隊列上二分,單調隊列主要是用來快速解決區間最值問題。
  編的時候出現了三個問題:
  1. manacher算法中忘記更行mx,id變量,導致其退化成O(n^2),在這個問題調試的時候我確信了manacher算法複雜度是嚴格O(n)的。
  2. 單調隊列中兩相鄰元素所夾區間應屬於後面一個元素。
  3. 這樣得題數組大小一定要準確,如果所有下標範圍都開大一倍一定會MLE
  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<ctime>
  6. #include<cmath>
  7. #include<algorithm>
  8. #include<set>
  9. #include<map>
  10. #include<vector>
  11. #include<string>
  12. #include<queue>
  13. using namespace std;
  14. #ifdef WIN32
  15. #define LL "%I64d"
  16. #else
  17. #define LL "%lld"
  18. #endif
  19. #define MAXN 2100
  20. #define MAXV MAXN*2
  21. #define MAXE MAXV*2
  22. #define INF 0x3f3f3f3f
  23. #define INFL 0x3f3f3f3f3f3f3f3fLL
  24. typedef long long qword;
  25. inline int nextInt()
  26. {
  27. char ch;
  28. int x=;
  29. bool flag=false;
  30. do
  31. ch=(char)getchar(),flag=(ch=='-')?true:flag;
  32. while(ch<''||ch>'');
  33. do x=x*+ch-'';
  34. while (ch=(char)getchar(),ch<='' && ch>='');
  35. return x*(flag?-:);
  36. }
  37.  
  38. int n,m;
  39. typedef int arr_t[MAXN];
  40. typedef int arr2[MAXN*];
  41. typedef arr_t map_t[MAXN];
  42. map_t a,b;
  43. map_t sa,sb,tsb,tsa;
  44.  
  45. void manacher(arr2 seq,int n,arr2 &res)
  46. {
  47. int id,mx;
  48. int i,j;
  49. id=mx=-;
  50. int cnt=;
  51. for (i=;i<n;i++)
  52. {
  53. if (i<mx)
  54. {
  55. res[i]=min(mx-i,res[id*-i]);
  56. }else res[i]=;
  57. while (i-res[i]->= && i+res[i]+<n && seq[i+res[i]+]==seq[i-res[i]-])
  58. {
  59. res[i]++;
  60. //cnt++;
  61. }
  62. if (i+res[i]>mx)//Do not forget
  63. {
  64. mx=i+res[i];
  65. id=i;
  66. }
  67. }
  68. return ;
  69. }
  70. void init_p(map_t mp,int n,int m,map_t &sl)
  71. {
  72. int i,j;
  73. arr2 seq,res;
  74. for (i=;i<n;i++)
  75. {
  76. for (j=;j<m;j++)
  77. {
  78. seq[j*+]=mp[i][j];
  79. seq[j*]=-INF;
  80. }
  81. seq[*m]=-INF;
  82. manacher(seq,*m+,res);
  83. for (j=;j<m;j++)
  84. {
  85. sl[i][j]=res[j*+];
  86. }
  87. }
  88. }
  89. int pseq[MAXN];
  90. int head,tail;
  91. map_t fa,fb,fc;
  92. void pm(map_t &a)
  93. {
  94. int i,j;
  95. for (i=;i<n;i++)
  96. {
  97. for (j=;j<m;j++)
  98. {
  99. printf("%d ",a[i][j]);
  100. }
  101. printf("\n");
  102. }
  103. printf("\n");
  104. }
  105.  
  106. void work(map_t &sa,map_t &sb,map_t &fa,int n,int m)
  107. {
  108. int i,j;
  109. for (i=;i<n;i++)
  110. for (j=;j<m/;j++)
  111. {
  112. swap(sb[i][j],sb[i][m-j-]);
  113. swap(sa[i][j],sa[i][m-j-]);
  114. }
  115. for (i=;i<n;i++)
  116. {
  117. head=,tail=;
  118. pseq[]=-;
  119. pseq[]=;
  120. fa[i][m-]=;
  121. for (j=;j<m;j++)
  122. {
  123. while (tail>=head && sb[i][j]<sb[i][pseq[tail]])tail--;
  124. pseq[++tail]=j;
  125. int l,r,mid;
  126. l=-,r=tail;
  127. while (l+<r)
  128. {
  129. int mid=(l+r)>>;
  130. if (sb[i][pseq[mid]]>=j-pseq[mid])
  131. r=mid;
  132. else
  133. l=mid;
  134. }
  135. fa[i][m-j-]=min(j-(pseq[l]+),min(sa[i][j],sb[i][pseq[r]]));
  136. }
  137. }
  138. for (i=;i<n;i++)
  139. for (j=;j<m/;j++)
  140. {
  141. swap(sb[i][j],sb[i][m-j-]);
  142. swap(sa[i][j],sa[i][m-j-]);
  143. }
  144.  
  145. for (i=;i<n;i++)
  146. {
  147. head=,tail=;
  148. pseq[]=-;
  149. pseq[]=;
  150. fa[i][]=;
  151. for (j=;j<m;j++)
  152. {
  153. while (tail>=head && sb[i][j]<sb[i][pseq[tail]])tail--;
  154. pseq[++tail]=j;
  155. int l,r,mid;
  156. l=-,r=tail;
  157. while (l+<r)
  158. {
  159. int mid=(l+r)>>;
  160. if (sb[i][pseq[mid]]>=j-pseq[mid])
  161. r=mid;
  162. else
  163. l=mid;
  164. }
  165. fa[i][j]=min(fa[i][j],min(j-(pseq[l]+),min(sa[i][j],sb[i][pseq[r]])));
  166. }
  167. }
  168. }
  169. int main()
  170. {
  171. //freopen("input.txt","r",stdin);
  172. //freopen("output.txt","w",stdout);
  173. int i,j,k;
  174. int x,y,z;
  175. int ans=;
  176. scanf("%d%d",&n,&m);
  177. memset(a,INF,sizeof(a));
  178. for (i=;i<n;i++)
  179. {
  180. for (j=;j<m;j++)
  181. {
  182. scanf("%d",&x);
  183. a[i*+][j*+]=x;
  184. b[j*+][i*+]=x;
  185. }
  186. }
  187. n*=;m*=;n++;m++;
  188. init_p(a,n,m,sa);
  189. init_p(b,m,n,tsb);
  190. for (i=;i<n;i++)
  191. for (j=;j<m;j++)
  192. sb[i][j]=tsb[j][i];
  193. for (i=;i<n;i++)
  194. {
  195. for (j=;j<m;j++)
  196. {
  197. sa[i][j]/=;
  198. sb[i][j]/=;
  199. }
  200. }
  201.  
  202. work(sa,sb,fa,n,m);
  203.  
  204. for (i=;i<n;i++)
  205. for (j=;j<m;j++)
  206. tsa[i][j]=a[i][j];
  207. for (i=;i<n;i++)
  208. for (j=;j<m;j++)
  209. b[i][m-j-]=a[m-j-][i]=tsa[i][j];
  210. swap(n,m);
  211. init_p(a,n,m,sa);
  212. init_p(b,m,n,tsb);
  213.  
  214. for (i=;i<n;i++)
  215. for (j=;j<m;j++)
  216. sb[i][j]=tsb[j][i];
  217. for (i=;i<n;i++)
  218. {
  219. for (j=;j<m;j++)
  220. {
  221. sa[i][j]/=;
  222. sb[i][j]/=;
  223. }
  224. }
  225. work(sa,sb,fb,n,m);
  226. for (i=;i<n;i++)
  227. for (j=;j<m;j++)
  228. tsb[i][j]=fb[i][j];
  229. swap(n,m);
  230. for (i=;i<n;i++)
  231. for (j=;j<m;j++)
  232. fb[i][j]=tsb[m-j-][i];
  233.  
  234. //pm(fa);
  235. //pm(fb);
  236. for (i=;i<n;i++)
  237. {
  238. for (j=;j<m;j++)
  239. {
  240. fc[i][j]=max(,min(fa[i][j]-(i%==),fb[i][j]-(j%==)));
  241. fc[i][j]=(fc[i][j]+)/;
  242. }
  243. }
  244. //pm(fc);
  245. for (i=;i<n;i++)
  246. {
  247. for (j=;j<m;j++)
  248. {
  249. if (i%+j%==)continue;
  250. ans+=fc[i][j];
  251. }
  252. }
  253. cout<<ans<<endl;
  254.  
  255. }

bzoj 1414: [ZJOI2009]对称的正方形 manacher算法+單調隊列的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ 2342 双倍回文(manacher算法)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2342 题意:定义双倍回文串为:串的长度为4的倍数且串的前一半.后一半.串本身均是回文的. ...

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

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

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

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

  8. manacher算法学习(求最长回文子串长度)

    Manacher总结 我的代码 学习:yyb luogu题目模板 xzy的模板 #include<iostream> #include<cstdlib> #include< ...

  9. 【学习笔记】Manacher算法

    本文部分图片来源 代码来源(代码是学姐哒.. 一.引入 Manacher算法是用来求最长回文子串的算法,时间复杂度O(n). 回文子串指的是''aacaa'',''noon'',这种正着反着读都一样的 ...

随机推荐

  1. 经典SQL语句大全之基本函数

    SQL Server基本函数 1.字符串函数 长度与分析用 1,datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格2,substring(expression,sta ...

  2. 使用lua给wireshark编写uTP的Dissector

      lonelycastle做uTP的实验,使用wireshark捕包,但是最初没有找到wireshark下的uTP的dissector,每次都需要比对文档,这样做实验理解报文含义,效率非常低.作为程 ...

  3. PureMVC(JS版)源码解析(十):Controller类

          这篇博客我们继续讲解PureMVC的三大核心类(View/Controller/Model)——Controller类.根据PureMVC模块设计,Controller类保存所有的Comm ...

  4. javascript常用方法(慢慢整理)

    获取类型:[object object],[object function],[object Undefined]等 Object.prototype.toString.apply(obj); 获取对 ...

  5. Binding 中 Elementname,Source,RelativeSource 三种绑定的方式

    在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...

  6. 我的插件のinput文本框实现宽度自适应

    先来最后结果:DEMO 介绍一下如何让一个文本框的宽度能够随着文本框中的内容的宽度增长而增长,也就是能够实现宽度自适应效果. 代码实例如下: <!DOCTYPE html> <htm ...

  7. javascript 【js‘s word】

    http://mp.weixin.qq.com/s?__biz=MjM5MzY2NDY0Ng==&mid=214013689&idx=1&sn=21e03f6c7bf73893 ...

  8. (转)META http-equiv="refresh" 实现网页自动跳转

    ***.html自动跳转文件代码如下: <HTML> <HEAD><META http-equiv="Refresh" content="5 ...

  9. 使用Delphi读取网络上的文本文件,html文件

    使用Delphi读取网络上的txt和html文件 可以使用两种方法: 1.下载文件,然后进行读取 下载文件的Delphi代码可以参考: http://www.delphibbs.com/delphib ...

  10. Oracle计算时间函数(numtodsinterval、numtoyminterval)

    numtodsinterval(<x>,<c>) ,x是一个数字,c是一个字符串,表明x的单位,这个函数把x转为interval day to second数据类型 常用的单位 ...