51nod 1158 全是1的最大子矩阵(单调栈 ,o(n*m))

前置问题:51nod 1102 面积最大的矩形

附上链接:
51nod 1102 面积最大的矩形
这题的题解博客

需要了解的知识:单调栈,在前置问题中已经讲解。

解题思路

  1. 对每行求左边连续1的个数,得到数组a[i][j];
  2. 对于第j列,找出每个位置i的数字a[i][j]上面第一个比它小数字l,和下面第一个比它小的数字r。
  3. 由这个点所在列为底,这个点的数字为最小值产生的矩形的面积为a[i][j]*(r-l-1),用这一列每一个面积更新ans。
  4. 上面2的求法就是单调栈了,总时间复杂度o(n*m)。

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[510][510];
int l[510],r[510];
int main(){
    ios::sync_with_stdio(false);
    int m,n;
    cin >> m >> n;
    for(int i = 1;i <= m; ++i){
        for(int j = 1;j <= n; ++j){
            cin >> a[i][j];
            if(a[i][j] == 1)  a[i][j] += a[i][j-1];
        }
    }
    int ans = 0;
    for(int i = 1;i <= n; ++i){
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        stack<int> s;
        s.push(1);
        a[0][i] = a[m+1][i] = -1;
        for(int j = 2;j <= m+1; ++j){
            while(s.size() and a[j][i] < a[s.top()][i]){
                r[s.top()] = j;
                s.pop();
            }
            s.push(j);
        }
        while(s.size()) s.pop();
        s.push(m);
        for(int j = m-1;j >= 0; --j){
            while(s.size() and a[j][i] < a[s.top()][i]){
                l[s.top()] = j;
                s.pop();
            }
            s.push(j);
        }
        for(int j = 1;j <= m; ++j){
            ans = max(ans, (r[j]-l[j]-1)*a[j][i]);
        }
    }
    cout << ans << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/zhangjiuding/p/9190292.html

时间: 2024-10-13 10:52:01

51nod 1158 全是1的最大子矩阵(单调栈 ,o(n*m))的相关文章

HDU -1506 Largest Rectangle in a Histogram&amp;&amp;51nod 1158 全是1的最大子矩阵 (单调栈)

单调栈和队列讲解:传送门 HDU -1506题意: 就是给你一些矩形的高度,让你统计由这些矩形构成的那个矩形面积最大 如上图所示,如果题目给出的全部是递增的,那么就可以用贪心来解决 从左向右依次让每一个矩形的高度当作最后的高度,来从中选取最大值就可以了 但是如果它不是递增的,中间会出现低谷,那么要还想运用贪心策略就要把之前高度大于它的全部扔掉,但是再扔掉他们之前还要判断一下以他们为最后答案的高度可不可行,这样我们就是在构造一个递增序列,可以用栈来维护它 代码: 1 #include<stdio.

51nod 1158 全是1的最大子矩阵

题目链接:51nod 1158 全是1的最大子矩阵 题目分类是单调栈,但是直接用与解最大子矩阵类似的办法水过了.. 1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 #define CLR(a,b) memset((a),(b),sizeof((a))) 6 using namespace std; 7 const int N = 501; 8 c

1158 全是1的最大子矩阵

1158 全是1的最大子矩阵 基准时间限制:1 秒 空间限制:131072 KB 给出1个M*N的矩阵M1,里面的元素只有0或1,找出M1的一个子矩阵M2,M2中的元素只有1,并且M2的面积是最大的.输出M2的面积. Input 第1行:2个数m,n中间用空格分隔(2 <= m,n <= 500) 第2 - N + 1行:每行m个数,中间用空格分隔,均为0或1. Output 输出最大全是1的子矩阵的面积. Input示例 3 3 1 1 0 1 1 1 0 1 1 Output示例 4思路:

51nod1158 全是1的最大子矩阵

跟最大子矩阵差不多O(n3)扫一下.有更优写法?挖坑! #include<cstdio> #include<cstring> #include<cctype> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) int read(){ int x=0;ch

数据结构--单调栈--求最大子矩阵的大小

求最大子矩阵的大小给定一个整型矩阵map, 其中的值只有0和1两种, 求其中全是1的所有矩形区域中, 最大的矩形区域为1的数量.例如:1 1 1 0其中, 最大的矩形区域有3个1, 所以返回3.再如:1 0 1 11 1 1 11 1 1 0其中, 最大的矩形区域有6个1, 所以返回6. 解:将其放到一个矩阵中,同时从第0行开始计算,以该行打底时,直方图的最大面积 如第0行,数组为[1, 0, 1, 1] 此时按照下面的求直方图最大面积. 然后以第1行打底,此时数组为[2, 1, 2, 2],同

51nod 1215 单调栈/迭代

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1215 1215 数组的宽度 题目来源: Javaman 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 N个整数组成的数组,定义子数组a[i]..a[j]的宽度为:max(a[i]..a[j]) - min(a[i]..a[j]),求所有子数组的宽度和. Input 第1行:1个数N,表示数组的长度.(1 <= N <=

51nod 1102 面积最大的矩形(单调栈)

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1102 题意: 思路: 做法就是求出每个长方形向左向右所能延伸的最大距离. 我这里用单调栈来做,维护一个单调递增的栈(自底向上递增),如果当前值大于栈顶,那么直接进栈,如果小于的话,那就说明前面比它大的那些数最多只能延伸到它这里.自己手动模拟一下就可以了. 1 #include<iostream> 2 #include<algorithm> 3 #inclu

51nod 1102 面积最大的矩形 &amp;&amp; 新疆大学OJ 1387: B.HUAWEI&#39;s billboard 【单调栈】+【拼凑段】(o(n) 或 o(nlog(n))

题面1: ? 题面2: ? 两道题除了数据范围不同,没有任何差异,两道题都可以o(n)(单调栈),o(nlog(n))(我自己的做法)解决. 解题思路1:(单调栈) 对于每个点找到右边第一个比它小的位置con1,并且找到左边第一个比它小的位置con2. 对于每个点更新答案为ans = max(ans, (con2-con1-1)*value[i]). 1的做法是两次裸的单调栈,时间复杂度为o(n). 代码1: #include <bits/stdc++.h> using namespace s

[51nod 1288]汽油补给(ST表+单调栈)

[51nod 1288]汽油补给(ST表+单调栈) 题面 有(N+1)个城市,0是起点N是终点,开车从0 -> 1 - > 2...... -> N,车每走1个单位距离消耗1个单位的汽油,油箱的容量是T.给出每个城市到下一个城市的距离D,以及当地的油价P,求走完整个旅途最少的花费.如果无法从起点到达终点输出-1. 分析 贪心考虑,当我们到达一个城市x的时候,我们下一个到的城市应该是在x加满油的情况下,能到达的油价比x低的城市.如果每个加油城市之间的路都这样走,那么最后的价钱一定是最小的.