【刷题】【单调栈】请客

神奇做法,神奇算法

#include<cstdio>
#include<cstdlib>
#include<stack>
#include<algorithm>
using namespace std;
int n,m;
const int N=303;
int d[N][N],mn[N],f[N];
int ans[N*N];

stack <int > s;
void calc()
{
    int sum;
    for(int i=1;i<=n;i++)
    {
        sum=1,f[i]=1;//初始化 
        while(!s.empty() && mn[s.top() ] > mn[i] )//然后从这一行向上扩展 
        {
            f[i]+=f[s.top() ];
            ans[mn[s.top() ] ]+=f[s.top() ]*sum;
            
            sum+=f[s.top() ];
            s.pop() ;
        }
        s.push(i); 
    }
    sum=1;
    while(!s.empty() )
    {
        ans[mn[s.top() ] ]+=f[s.top() ]*sum;
        sum+=f[s.top() ];
        s.pop() ;
    }
}

int main()
{
    //input
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&d[i][j]);
    //work
    for(int i=1;i<=m;i++)//枚举左端点
    {
        for(int j=1;j<=n;j++) mn[j]=d[j][i];
        calc();
        
        for(int j=i+1;j<=m;j++)//枚举右端点 
        {
            for(int k=1;k<=n;k++)
                mn[k]=min(mn[k],d[k][j]);//一行一行的得到mn值  
            calc();//求左右端点之间,以各行结尾的矩形数 
        }
    }
    //output
    int mx=n*m;
    for(int i=1;i<=mx;i++) printf("%d
",ans[i]);
    return 0;
} 
原文地址:https://www.cnblogs.com/xwww666666/p/11837459.html