二维单调栈

http://poj.org/problem?id=3494

题意:给出一个01矩阵,问最大的全为1的子矩阵。

解法:将预处理后,将每一列(行)看成一维单调栈。

//#include<bits/stdc++.h>
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
using namespace std ;
typedef long long ll ;
const int N = 2010, M = 200010 ;
int n , m ;
int a[N][N];
int st[N] , top ;
int b[N];
int len[N];
int work(){
    top = 0 ;
    int cnt = 0 ;
    for(int i = 0 ; i < m ; i++) len[i] = 1 ; 
    for(int i = 0 ; i < m ; i++){
        cnt = 0 ;
        while(top && b[i] <= b[st[top]]){
            len[st[top]] += cnt ;
            cnt = len[st[top]] ;
            top--;
        }
        len[i] += cnt ;
        st[++top] = i ;
    }
    cnt = 0 ;
    while(top){
        len[st[top]] += cnt ;
        cnt = len[st[top]] ;
        top--;
    }
    int ans = 0 ;
    for(int i = 0 ; i < m ; i++){
        ans = max(ans , b[i]*len[i]);
    }
    return ans ;
}

void solve(){
    for(int i = 0 ; i < n ; i++){
        for(int j = 0 ; j < m ; j++){
            scanf("%d" , &a[i][j]);
        }
    }
    for(int i = 0 ; i < n ; i++){
        for(int j = 0 ; j < m ; j++){
            if(a[i][j] == 1){
                if(i && a[i-1][j]){
                    a[i][j] += a[i-1][j] ;
                }
            }
        }
    }
    int ans = 0 ;
    for(int i = 0 ; i < n ; i++){
        for(int j = 0 ; j < m ; j++){
            b[j] = a[i][j] ;
        }
        ans = max(ans , work());
    }
    cout << ans << endl;
}

signed main(){
    #ifdef ONLINE_JUDGE
	#else
		freopen("D:\c++\in.txt", "r", stdin);
		//freopen("D:\c++\out.txt", "w", stdout);
	#endif
    while(~scanf("%d%d" , &n , &m))
        solve();
    
}
原文地址:https://www.cnblogs.com/nonames/p/12317495.html