1 条题解

  • 1
    @ 2024-12-11 16:08:13

    解决这个问题之前我们先讲一个新知识点,对于一行连续的柱形图,如何求出最大的矩形面积。

    设当前柱形高度为 hhll 为当前元素左边第一个高度小于它的柱形的位置,rr 为右边第一个,计 tt 为扩展出的矩形的面积 (rl1)h(r - l - 1) * h,最终答案为所有的 tt 取最大。

    /**
     *    author: 小飞侠
     *    created: 2024.12.11 15:59:04
     */
    #include <iostream>
    using namespace std;
    const int N = 3010;
    int l[N], r[N], q[N];
    int g[N][N], h[N][N];
    int n, m, p;
    int res;
    int cal(int h[])//计算这一行为底的最大矩形面积
    {
        int top = 0;
        l[0] = -1, h[m + 1] = -1;
        for(int i = 1; i <= m; ++ i)
        {
            while(top && h[q[top]] >= h[i]) -- top;
            if(!top) l[i] = 0;
            else l[i] = q[top];
            q[++ top] = i;
        }//l[m]存储 m 个元素左边第一个小于他的元素的位置
        top = 0;
        for(int i = m; i >= 1; -- i)
        {
            while(top && h[q[top]] >= h[i]) -- top;
            if(!top) r[i] = m + 1;
            else r[i] = q[top];
            q[++ top] = i;
        }//r[m]存储 m 个元素右边第一个小于他的元素的位置
        int res = 0;
        for(int i = 1; i <= m; ++ i) res = max(res, (r[i] - l[i] - 1) * h[i]);//所有的 t
        return res;
    
    }
    int main()
    {
        cin >> n >> m >> p;
        while(p --)
        {
            int x, y;
            cin >> x >> y;
            g[x][y] = 1;
        }
    
        for(int i = 1; i <= n; ++ i)
        {
            for(int j = 1; j <= m; ++ j)
            {
                if(!g[i][j]) h[i][j] = h[i - 1][j] + 1;
            }
        }//用 h 数组模拟出柱形图
        //h[i] 这一行数表示的是第 i 行为底的柱形图每一列的高度
    
        for(int i = 1; i <= n; ++ i) res = max(res, cal(h[i]));//暴力枚举任意一行为底部的柱形图
    
        cout << res << '\n';
        return 0;
    }
    
    • 1

    信息

    ID
    5520
    时间
    1000ms
    内存
    256MiB
    难度
    5
    标签
    递交数
    8
    已通过
    2
    上传者