算法竞赛进阶指南---0x18(单调栈)City Game

题面

在这里插入图片描述

题解

在这里插入图片描述

  1. 我们可以枚举每一行,记录这一行每列连续 F 的个数(如图枚举到第四行) ,F的个数可以从第一行递推求出,这样问题就转化成算法竞赛进阶指南—0x11(栈) 直方图中最大的矩形
  1. 对于每一行,我们可以枚举每个高度所能组成的面积最大的长方形,然后取一个最大值即可。就看题中的样例,对于第四列的,只有左右两边的高度>=4 才能组成要枚举的长方形,那么就要求左右两边的小长方形高度最小为4,可以看到,左边没有,右边2个,所以面积为( 7 - 3 - 1 ) * 4 = 12
  1. 那么转化就是,我们可以记录左边离他最近且小于它的高度的下标,右边离他最近且小于它高度的下标,那么(右-左-1)就是这个高度对应的最长的长度,这不就是单调栈的应用嘛

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>

using namespace std;
const int N = 1010;

int n, m;
char g[N][N];
int f[N][N];


int main() {
    
    

    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    cin >> n >> m;

    for (int i = 1; i <= n; i++) {
    
    
        for (int j = 1; j <= m; j++) {
    
    
            cin >> g[i][j];
            if (g[i][j] == 'F') f[i][j] = f[i - 1][j] + 1;
            else f[i][j] = 0;
        }
    }

    int res = 0;
    for (int i = 1; i <= n; i++) {
    
    

        int stk[N], tt = 0, l[N], r[N];
        for (int j = 1; j <= m; j++) {
    
    
            while (tt && f[i][stk[tt]] >= f[i][j]) tt--;
            if (tt) l[j] = stk[tt];
            else l[j] = 0;
            stk[++tt] = j;
        }

        tt = 0;
        for (int j = m; j > 0; j--) {
    
    
            while (tt && f[i][stk[tt]] >= f[i][j]) tt--;
            if (tt) r[j] = stk[tt];
            else r[j] = m + 1;
            stk[++tt] = j;
        }

        for (int j = 1; j <= m; j++) {
    
    
            res = max(res, (r[j] - l[j] - 1) * f[i][j]);
        }
    }

    cout << res * 3 << endl;

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_44791484/article/details/113984298