[ZJOI2007] 棋盘制作(单调栈 / DP悬线法)
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悬线法)相关推荐
- BZOJ-1057: [ZJOI2007]棋盘制作(单调栈)
1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 3096 Solved: 1567 [Submit][St ...
- P1169 [ZJOI2007]棋盘制作 DP悬线法
题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白 ...
- 算法学习笔记(2) 悬线法
本文属于「算法学习」系列文章之一.之前的[数据结构和算法设计]系列着重于基础的数据结构和算法设计课程的学习,与之不同的是,这一系列主要用来记录对大学课程范围之外的高级算法学习.优化与使用的过程,同时也 ...
- [ZJOI2007]棋盘制作 悬线法dp 求限制下的最大子矩阵
https://www.luogu.org/problemnew/show/P1169 第一次听说到这种dp的名称叫做悬线法,听起来好厉害 题意是求一个矩阵内的最大01交错子矩阵,开始想的是dp[20 ...
- P1169 [ZJOI2007]棋盘制作(悬线法)
题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8 \times 88×8大小的黑白相间的方阵,对应八八六十四卦,黑白 ...
- 【BZOJ-30391057】玉蟾宫棋盘制作 悬线法
3039: 玉蟾宫 Time Limit: 2 Sec Memory Limit: 128 MB Submit: 753 Solved: 444 [Submit][Status][Discuss] ...
- bzoj 1057: 棋盘制作(悬线法)
1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 2311 Solved: 1146 [Submit][St ...
- 洛谷 P4147 玉蟾宫【悬线法/单调栈】
题目背景 有一天,小猫 rainbow 和 freda 来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. 题目描述 这片土地被分成 N×MN\times MN×M ...
- 【BZOJ1057】【codevs1428】棋盘制作,悬线法
传送门1 传送门2 思路: 比较简单的悬线法 相关资料自行百度 看一会就能明白的 反正这个就是模板题啦(敲桌) 虽然说好不发水题了,但这次发上来也就是给大家也给自己当个板子使-- 代码: #inclu ...
最新文章
- 一文搞懂faiss计算
- windows下pomelo开发环境搭建及JS乱码问题
- linux下vi命令大全[转]
- element ui 红点_element-ui 自定义表单验证 , 但是不出现小红心了
- python零基础学习教程之Python 运算符
- iOS中下载大型文件的原理解析二
- 为什么Java里面的静态方法不能是抽象的
- Angular4学习笔记(六)- Input和Output
- idea 开启Run DashBoard
- 【分布计算环境学习笔记】4 Enterprise Java Bean
- GDAL学习笔记——OGR投影
- python定义整型数组_Python数组定义方法
- python小工具—窗口轰炸
- dataV实现扇形图轮播
- MATLAB 渐进式形态学滤波
- CCNP精粹系列之二十九--发布bgp子网信息,推荐
- 电影网站 php asp,大站长电影网址大全 ASP版 v20180507
- 华清远见嵌入式培训_第一周回顾与反思
- matlab模拟神经模糊自适应控制器
- 回顾RHCE——虚拟主机
热门文章
- 数学特级教师:数学除了做习题,我还他让他们看这十部纪录片!
- 21张GIF动图让你秒懂数学原理
- 信心满满的去面算法工程师,竟然凉了...
- linux命令clock,简单了解Linux系统中clock命令的使用方法
- html2canvas改成同步,html2canvas转为图片异步转同步问题(记录)
- jq动态获取input的值传给html,jquery 保证html()拿到的html字符串包含input的value值
- powerbi视觉对象_玩转Power BI的图片可视化
- python插入排序_python 插入排序,选择排序
- spring boot 中@Mapper和@Repository的区别
- 7-2 一元多项式的乘法与加法运算 (20 分)(思路加详解+map做法)map真香啊 各个测试点的用例子 来吧宝贝!