洛谷P1950

P1950 长方形
绿题,比赛依旧暴力吧,我算是发现了,绿题就是我智商上限了

这题其实和P4147一样需要借助悬线,不同点在于一个求组合数,一个求最大值

点击查看代码
#include<bits/stdc++.h>
#define MAXN 1010
using namespace std;

char ch[MAXN][MAXN];
int n, m, top;
int h[MAXN], l[MAXN], r[MAXN], st[MAXN];
long long ans;

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for(int j = 1; j <= m; j++) cin >> ch[i][j];
    }
    for(int i = 1; i <= n; i++) {//以行为单位进行处理
        for(int j = 1; j <= m; j++) h[j] = ch[i][j] == '*' ? 0 : h[j] + 1;//h数组的处理有点像悬线

        top = 0;//重置单调栈,处理r数组
        for(int j = 1; j <= m; j++) {
            while(top > 0 && h[j] < h[st[top]]) {
                r[st[top]] = j;
                top--;
            }
            top++;
            st[top] = j;
        }
        while(top > 0) {
            r[st[top]] = m + 1;
            top--;
        }
        //r[i]为该列右边第一个满足h值小于h[i]的下标号
        //没有找到就是m+1
        //这里自然是使用单调栈进行处理
        
        top = 0;
        for(int j = m; j >= 1; j--) {
            while(top > 0 && h[j] <= h[st[top]]) {
                l[st[top]] = j;
                top--;
            }
            top++;
            st[top] = j;
        }
        while(top > 0) {
            l[st[top]] = 0;
            top--;
        }
        //l[i]为该列左边第一个满足h值小于等于h[i]的下标号
        //没有找到就是0
        //处理方法与r数组类似
        
        for(int j = 1; j <= m; j++) {
            ans += (j - l[j]) * (r[j] - j) * h[j];
        }
        //想要理解这一部分建议参考《深入浅出(进阶)》P014 图1-6
    }
    cout << ans;
    return 0;
}
posted @ 2025-05-09 20:07  Chuan81  阅读(9)  评论(0)    收藏  举报