单调栈求矩阵最大面积

本文讨论了一种改进的悬线法,指出在处理问题时,悬线法可能只需记录一侧(R或L数组)的数据即可。通过实例代码,作者分享了如何简化存储并解决实际问题的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

杭电多校 题目链接

略微有点不一样的是,这次的悬线并没有记录R,L,数组,因为左右可延伸的长度只与竖直方向有关系。

不过这道题让我多了个疑惑,悬线法是否可以仅仅记录一边就行了,就是R或者L数组仅取就一个就行,以后再来补补吧。

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

using namespace std;

inline int read() {
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
inline int Readc() {
    char c = getchar();
    while (c != 'R' && c != 'F')c = getchar();
    if (c == 'F')return 1;
    return 0;
}//F能用,E不能用
inline int max(int x, int y) {
    return x > y ? x : y;
}

inline int min(int x, int y) {
    return x < y ? x : y;
}

//max和min最好自己打
int n, m, ans1, ans, map[2000][2005];;
int g[2005][2005];
int h[2000];
int que[2000];
//向上到达最远的点的距离
int main() {
   int t;
   cin>>t;
   while(t--){

       ans = 0;
       n = read(), m = read();
       for (int i = 1; i <= n; i++)
           for (int j = 1; j <= m; j++)
               g[i][j]=read();

       for (int i = 1; i <= m; i++) {
           int len = 1;
           for (int j = 2; j <= n; j++) {
               if (g[j][i] >= g[j - 1][i]) {
                   map[j][i] = map[j - 1][i] = len;
               } else {
                   len++;
                   map[j][i] = 0;
                   if (j - 1 == 1)map[j - 1][i] = 0;
               }
           }
       }
//        for(int i=1;i<=n;i++) {
//            for (int j = 1; j <= m; j++) {
//                cout << map[i][j] << ' ';
//            }
//            cout<<endl;
//        }
       int ans = 0;
       for (int i = 1; i <= n; i++) {
           for (int j = 1; j <= m; j++) {
               if (i == 1) {
                   h[j] = 1;
               } else if (map[i - 1][j] == map[i][j] && map[i][j] != 0) {
                   h[j]++;
               } else h[j] = 1;
           }
           int tot = 0;
           h[m + 1] = 0;
           for (int j = 1; j <= m + 1; j++) {
               while (tot && h[que[tot]] > h[j]) {
                   //cout << (j - que[tot - 1] - 1) * h[que[tot]];
                   ans = max(ans, (j - que[tot - 1] - 1) * h[que[tot]]);
                   //printf("%d %d %d\n",j,que[tot-1],h[que[tot]]);
                   tot--;
                   //cout<<ans<<' ';
               }
               que[++tot] = j;
           }
       }
       printf("%d\n", ans);
   }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值