zoukankan      html  css  js  c++  java
  • 51nod 1158 全是1的最大子矩阵

    题目链接在这儿

    如果我的博客费解,可以看这篇博客,认为清晰。

    首先把子矩阵预处理,g[i][j]表示第[i][j]号元素能向左延伸的长度。

    进而针对每一列,假设是c列,考虑g[i][c],i∈[1, Row],得到g[i][c]元素在这一列上作为作为最小值的长度。

    假设这个区间是(U, D),那么长度为D-U-1,那么临时解为(D-U-1)*g[i][j]。取临时解中的最大值即为答案。

    这里要利用单调栈,或者用我用的比较简洁的写法都ok,理解了解法自己写比较好,复杂度O(N^2)。

    为何是这样:举个例子,假设有下面描述的第5列左连续的值为2 4 3 5 2:

    00011

    01111

    00111

    11111

    00011

    考虑第三行第五列的值3,在这列上它作为最小值的开区间是(1, 5),闭区间是[2, 4],一个解即为(5-1-1)*3=9。

    对代码的解释:U[i]和D[i]分别表示列上某一元素i,作为最小值能覆盖的左开区间点UP和右开区间点DOWN。

    #include <stdio.h>
    #include <iostream>
    using namespace std;
    
    const int maxN=5e2+5;
    int N, M, K, T;
    int g[maxN][maxN], U[maxN], D[maxN];
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.in", "r", stdin);
    #endif
        scanf("%d%d", &N, &M);
        for (int i = 1; i <= N; ++i) {
            for (int j = 1; j <= M; ++j) {
                scanf("%d", &g[i][j]);
                if (g[i][j])
                    g[i][j] = g[i][j - 1] + 1;
            }
        }
        int ans = 0;
        for (int c = 1; c <= M; ++c) {
            for (int i = 1; i <= N; ++i) {
                U[i] = i - 1;
                D[i] = i + 1;
            }
            for (int r = 1; r <= N; ++r)
                while (U[r] && g[U[r]][c] >= g[r][c])
                    U[r] = U[U[r]];
            for (int r = N; r >= 1; --r)
                while (D[r] <= N && g[D[r]][c] >= g[r][c])
                    D[r] = D[D[r]];
            for (int r = 1; r <= N; ++r)
                ans = max(ans, (D[r] - U[r] - 1) * g[r][c]);
        }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    AD预测论文研读系列2
    hdu 5795
    sg函数的应用
    二分查找
    快速幂
    筛选法素数打表
    多校hdu-5775 Bubble sort(线段树)
    多校hdu5754(博弈)
    多校hdu5738 寻找
    多校hdu5726 线段树+预处理
  • 原文地址:https://www.cnblogs.com/Rosebud/p/9522954.html
Copyright © 2011-2022 走看看