P4147 玉蟾宮

纯粹的發表於2024-03-10

原題連結

題解

太巧妙了

把每個點上方的連續f長度記錄下來,然後求每行的柱狀圖構成的矩形的最大面積

code


#include<bits/stdc++.h>
using namespace std;
int f[1005][1005]={0};
int n,m;

struct node
{
    int h,cnt;
};

int solve(int row)//每一行列上的高度,如果全部使用,不是作為左端點就是作為右端點
{
    int ans=0;
    stack<node> q;//相當於求左邊最遠小於自己的值,右邊最遠小於自己的值,單調棧解法
    for(int j=1;j<=m;j++)
    {
        int cnt=0;
        while(q.size()&&q.top().h>=f[row][j])
        {
            cnt+=q.top().cnt;//cnt代表這個點收納了多少點
            ans=max(ans,q.top().h*cnt);//作為左端點更新,即後邊遇到了比自己更小的值,然後彈出
            q.pop();//如果彈出,代表遇到了作為左端點的最遠距離的點
        }

        ans=max(ans,f[row][j]*(cnt+1));//作為右端點更新,找到左邊比自己小的點
        q.push({f[row][j],cnt+1});//cnt代表該元素左邊有多少不小於自己的(包括自己)
    }

    int cnt=0;
    while(q.size())//有些元素沒有作為左端點更新過
    {
        ans=max(ans,(cnt+1)*q.top().h);
        cnt+=q.top().cnt;
        q.pop();
    }
    return ans;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            char op;
            cin>>op;
            if(op=='F') f[i][j]=f[i-1][j]+1;//記錄以該點為下端點,最長連續f的長度
        }
    }

    int ans=0;
    for(int i=1;i<=n;i++)
    {
        ans=max(ans,solve(i));//變成求每行的最大矩形
    }

    cout<<3*ans;
    return 0;
}

相關文章