牛客三F Planting Trees

https://ac.nowcoder.com/acm/contest/883/F?&headNav=acm
牛客三F Planting Trees_第1张图片
枚举上下边界,然后,枚举右边界,合法的矩形左边界关于右边界向右而向右,用单调队列来做。
这题卡RMQ,并且卡STL。

#include
using namespace std;
const int maxn=600;

int T,n,m,a[maxn][maxn],Max[maxn],Min[maxn];

int main()
{
    //freopen("input.in","r",stdin);
    cin>>T;
    while(T--)
    {
        int ans=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)scanf("%d",&a[i][j]);
        for(int up=1;up<=n;up++)
        {
            for(int down=up;down<=n;down++)
            {
                for(int c=1;c<=n;c++)
                    if(up==down)Max[c]=Min[c]=a[down][c];
                    else Max[c]=max(Max[c],a[down][c]),Min[c]=min(Min[c],a[down][c]);
                int qmax[maxn],qmin[maxn],smin=1,tmin=0,smax=1,tmax=0;
                int l=1;
                for(int r=1;r<=n;r++)
                {
                    while(smin<=tmin && Min[qmin[tmin]]>=Min[r])tmin--;
                    while(smax<=tmax && Max[qmax[tmax]]<=Max[r])tmax--;
                    qmax[++tmax]=qmin[++tmin]=r;
                    while(smin<=tmin && smax<=tmax && Max[qmax[smax]]-Min[qmin[smin]]>m)
                    {
                        if(qmin[smin]==l)smin++;
                        if(qmax[smax]==l)smax++;
                        l++;
                    }
                    ans=max(ans,(down-up+1)*(r-l+1));
                }
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

你可能感兴趣的:(单调栈/单调队列)