problem

洛谷链接

solution1-单调栈

很容易想到,预处理出每个点向上最大能延伸的长度,然后对每个点求一个矩阵面积。

然后思考优化,不难想到每次对一行进行求解。

每一行的所有列一起构成了一个直方图。

直方图直接经典笛卡尔树。笛卡尔树性质是什么?是单调栈!

直接对每一行都建一个单调栈,遍历列维护递增栈,弹出时计算答案。正方形将两边取个 min⁡\minmin 再比就行了。

这个做法很简单,但是直观上是 O(n3)O(n^3)O(n3) 的,所以很多人不敢打。

但实际上跑很快,因为每个点只会被做一次。一次单调栈是做连续一段。

时间复杂度应该是 O(n2)O(n^2)O(n2) 的。

#include <bits/stdc++.h>
using namespace std;
#define maxn 2005
int n, m, top, ans1, ans2;
int h[maxn], s[maxn];
int c[maxn][maxn];int main() {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )scanf( "%d", &c[i][j] );for( int i = 1;i <= n;i ++ ) { //枚举每一行for( int j = 1;j <= m;j ++ ) //预处理该行上每一列最长能向上延伸的长度if( i > 1 and c[i][j] ^ c[i - 1][j] ) ++ h[j];else h[j] = 1;for( int j = 1, k;j <= m;j = k ) {s[0] = j - 1, s[top = 1] = j;for( k = j + 1;k <= m and c[i][k] ^ c[i][k - 1];k ++ ) {while( top and h[s[top]] > h[k] ) {ans1 = max( ans1, min(h[s[top]], k - s[top - 1] - 1) * min(h[s[top]], k - s[top - 1] - 1) );ans2 = max( ans2, h[s[top]] * (k - s[top - 1] - 1) );top --;}s[++ top] = k;}while( top ) {ans1 = max( ans1, min(h[s[top]], k - s[top - 1] - 1) * min(h[s[top]], k - s[top - 1] - 1) );ans2 = max( ans2, h[s[top]] * (k - s[top - 1] - 1) );top --;}}}printf( "%d\n%d\n", ans1, ans2 );return 0;
}

solution2-DP悬线法

最大子矩阵很熟悉啊!是 DPDPDP 入门必讲的经典例题。

对每一个位置 (i,j)(i,j)(i,j) 预处理出其向上/向左/向右分别能延伸到多远。

然后询问每一个位置 (i,j)(i,j)(i,j) 被包含的最大子矩阵,如果和上一行是合法的就要结合上一行的左右限制。

具体而言,左边限制取较大值,右边限制取较小值,本质是取最靠近 (i,j)(i,j)(i,j) 的左右两边限制。

取完后,矩形长即 r(i,j)−l(i,j)+1r(i,j)-l(i,j)+1r(i,j)−l(i,j)+1,宽即 h(i,j)h(i,j)h(i,j)。就可以求了。

这里需要注意的是,不能在预处理的时候,就考虑上一行的左右限制。

//这么写就是错的
for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )if( j > 1 and c[i][j] ^ c[i][j - 1] )if( h[i][j] > 1 ) l[i][j] = max( l[i - 1][j], l[i][j - 1] );else l[i][j] = l[i][j - 1];else l[i][j] = j;
for( int i = 1;i <= m;i ++ ) r[0][i] = m;
for( int i = 1;i <= n;i ++ )for( int j = m;j;j -- )if( j < m and c[i][j] ^ c[i][j + 1] )if( h[i][j] > 1 ) r[i][j] = min( r[i - 1][j], r[i][j + 1] );else r[i][j] = r[i][j + 1];else r[i][j] = j;

你过早的刻画了左右边界,就会出现上面这种。虽然对于紫红色点而言确实是这个矩形。

但对于后面的黄色点而言,其递推的左边界也被限制在了黑线处,就算不到红色矩形了。

#include <bits/stdc++.h>
using namespace std;
#define maxn 2005
int n, m;
int c[maxn][maxn], h[maxn][maxn], l[maxn][maxn], r[maxn][maxn];int main() {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )scanf( "%d", &c[i][j] );for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )if( i > 1 and c[i][j] ^ c[i - 1][j] ) h[i][j] = h[i - 1][j] + 1;else h[i][j] = 1;for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ )if( j > 1 and c[i][j] ^ c[i][j - 1] ) l[i][j] = l[i][j - 1];else l[i][j] = j;for( int i = 1;i <= n;i ++ )for( int j = m;j >= 1;j -- )if( j < m and c[i][j] ^ c[i][j + 1] ) r[i][j] = r[i][j + 1];else r[i][j] = j;int ans1 = 0, ans2 = 0;for( int i = 1;i <= n;i ++ )for( int j = 1;j <= m;j ++ ) {if( i > 1 and c[i][j] ^ c[i - 1][j] ) {l[i][j] = max( l[i][j], l[i - 1][j] );r[i][j] = min( r[i][j], r[i - 1][j] );}ans1 = max( ans1, min( r[i][j] - l[i][j] + 1, h[i][j] ) * min( r[i][j] - l[i][j] + 1, h[i][j] ) );ans2 = max( ans2, ( r[i][j] - l[i][j] + 1 ) * h[i][j] );}printf( "%d\n%d\n", ans1, ans2 );return 0;
}

[ZJOI2007] 棋盘制作(单调栈 / DP悬线法)相关推荐

  1. BZOJ-1057: [ZJOI2007]棋盘制作(单调栈)

    1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 3096  Solved: 1567 [Submit][St ...

  2. P1169 [ZJOI2007]棋盘制作 DP悬线法

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白 ...

  3. 算法学习笔记(2) 悬线法

    本文属于「算法学习」系列文章之一.之前的[数据结构和算法设计]系列着重于基础的数据结构和算法设计课程的学习,与之不同的是,这一系列主要用来记录对大学课程范围之外的高级算法学习.优化与使用的过程,同时也 ...

  4. [ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵

    https://www.luogu.org/problemnew/show/P1169 第一次听说到这种dp的名称叫做悬线法,听起来好厉害 题意是求一个矩阵内的最大01交错子矩阵,开始想的是dp[20 ...

  5. P1169 [ZJOI2007]棋盘制作(悬线法)

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白 ...

  6. 【BZOJ-30391057】玉蟾宫棋盘制作 悬线法

    3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MB Submit: 753  Solved: 444 [Submit][Status][Discuss] ...

  7. bzoj 1057: 棋盘制作(悬线法)

    1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 2311  Solved: 1146 [Submit][St ...

  8. 洛谷 P4147 玉蟾宫【悬线法/单调栈】

    题目背景 有一天,小猫 rainbow 和 freda 来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 题目描述 这片土地被分成 N×MN\times MN×M ...

  9. 【BZOJ1057】【codevs1428】棋盘制作,悬线法

    传送门1 传送门2 思路: 比较简单的悬线法 相关资料自行百度 看一会就能明白的 反正这个就是模板题啦(敲桌) 虽然说好不发水题了,但这次发上来也就是给大家也给自己当个板子使-- 代码: #inclu ...

最新文章

  1. 一文搞懂faiss计算
  2. windows下pomelo开发环境搭建及JS乱码问题
  3. linux下vi命令大全[转]
  4. element ui 红点_element-ui 自定义表单验证 , 但是不出现小红心了
  5. python零基础学习教程之Python 运算符
  6. iOS中下载大型文件的原理解析二
  7. 为什么Java里面的静态方法不能是抽象的
  8. Angular4学习笔记(六)- Input和Output
  9. idea 开启Run DashBoard
  10. 【分布计算环境学习笔记】4 Enterprise Java Bean
  11. GDAL学习笔记——OGR投影
  12. python定义整型数组_Python数组定义方法
  13. python小工具—窗口轰炸
  14. dataV实现扇形图轮播
  15. MATLAB 渐进式形态学滤波
  16. CCNP精粹系列之二十九--发布bgp子网信息,推荐
  17. 电影网站 php asp,大站长电影网址大全 ASP版 v20180507
  18. 华清远见嵌入式培训_第一周回顾与反思
  19. matlab模拟神经模糊自适应控制器
  20. 回顾RHCE——虚拟主机

热门文章

  1. 数学特级教师:数学除了做习题,我还他让他们看这十部纪录片!
  2. 21张GIF动图让你秒懂数学原理
  3. 信心满满的去面算法工程师,竟然凉了...
  4. linux命令clock,简单了解Linux系统中clock命令的使用方法
  5. html2canvas改成同步,html2canvas转为图片异步转同步问题(记录)
  6. jq动态获取input的值传给html,jquery 保证html()拿到的html字符串包含input的value值
  7. powerbi视觉对象_玩转Power BI的图片可视化
  8. python插入排序_python 插入排序,选择排序
  9. spring boot 中@Mapper和@Repository的区别
  10. 7-2 一元多项式的乘法与加法运算 (20 分)(思路加详解+map做法)map真香啊 各个测试点的用例子 来吧宝贝!