hihocoder[Offer收割]编程练习赛41:01间隔矩阵(单调栈求最大子矩形面积)

来源:互联网 发布:linux c 创建文件夹 编辑:程序博客网 时间:2024/06/05 15:47

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

给定一个N × M的01矩阵,小Hi希望从中找到一个01间隔的子矩阵,并且子矩阵的面积越大越好。

例如对于

0101010

1000101

0101010

1010101

0101010

在右侧有一个5 × 4的01间隔子矩阵,在下方有一个3 × 7的01间隔子矩阵。

输入

第一行包含两个整数N和M。  

以下N行M列包含一个N × M的01矩阵。  

对于30%的数据,1 ≤ N, M ≤ 250  

对于100%的数据,1 ≤ N, M ≤ 2000

输出

输出最大的01间隔子矩阵的面积。

样例输入
5 7  01010101000101010101010101010101010
样例输出
21
思路:预处理出d[i][j]:表示以(i,j)为起点向上延伸满足01间隔的最长长度。然后从第一行遍历到最后一行,用单调栈来计算最大面积并更新答案。

#include<bits/stdc++.h>using namespace std;const int MAX=1e6;const int MOD=1e9+7;typedef long long ll;char s[3000][3000];int d[3000][3000];struct lenka{    int h,tmp;};int main(){    int n,m;    cin>>n>>m;    for(int i=0;i<n;i++)scanf("%s",s[i]);    for(int i=0;i<n;i++)    {        for(int j=0;j<m;j++)        {            if(i==0||s[i][j]==s[i-1][j])d[i][j]=1;            else d[i][j]=d[i-1][j]+1;        }    }    int ans=0;    deque<lenka>p;    for(int i=n-1;i>=0;i--)    {        for(int j=0;j<m;j++)        {            if(j==0||s[i][j]==s[i][j-1])            {                p.clear();                p.push_front((lenka){d[i][j],1});                continue;            }            if(p.empty()||p.front().h<=d[i][j])p.push_front((lenka){d[i][j],1});            else            {                int tmp=0;                while(!p.empty()&&p.front().h>d[i][j])                {                    tmp+=p.front().tmp;                    ans=max(ans,p.front().h*tmp);                    p.pop_front();                }                p.push_front((lenka){d[i][j],tmp+1});            }        }        int tmp=0;        while(!p.empty())        {            tmp+=p.front().tmp;            ans=max(ans,p.front().h*tmp);            p.pop_front();        }    }    cout<<ans<<endl;    return 0;}




阅读全文
1 0
原创粉丝点击