2019牛客暑期多校训练营(第三场)F:Planting Trees(单调队列)

本文详细解析了一种求解给定区域内最大矩形面积的算法,该算法通过枚举上下边界和右边界,利用两个单调队列维护满足条件的最小左边界,从而更新最大面积。文中提供了完整的代码实现,包括初始化、更新最大最小值、维护单调队列及计算面积等关键步骤。

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

【题意】

给定区域大小n*n的网格和m,要求输出最大的矩形满足任意两个位置的差值不超过m的面积。

【题解】

思路:枚举上下边界和右边界,用两个单调队列维护最小左边界,更新最大面积。如何维护?以最大值为例,因为如果当前的最大最小值不满足<=m,那么我们需要更小的最大值,所以需要的单调队列是递减的,因此在维护的时候我们每次入队时弹出比当前最大值小的元素。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,a[505][505],mx[505],mn[505],la[505],ra[505];
int q1[505],q2[505],l1,l2,r1,r2;
int main()
{
    int T; scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&a[i][j]);
        int ans=0;
        for(int l=1;l<=n;l++){
            //初始化最大最小值
            memset(mx,0,sizeof mx);
            memset(mn,inf,sizeof mn);
            for(int r=l;r<=n;r++){
                l1=l2=r1=r2=0;
                for(int k=1,p=0;k<=n;k++){ //枚举右边界
                    //更新最大最小值
                    mx[k]=max(mx[k],a[r][k]);
                    mn[k]=min(mn[k],a[r][k]);

                    while(l1<r1&&mx[q1[r1-1]]<mx[k]) r1--; //弹出比MAX小的,保证单调队列递减
                    while(l2<r2&&mn[q2[r2-1]]>mn[k]) r2--; //弹出比MIN大的,保证单调队列递增

                    q1[r1++]=k,q2[r2++]=k; //进入单调队列

                    while(l1<r1&&l2<r2&&mx[q1[l1]]-mn[q2[l2]]>m){ //更新最小左边界
                        if(q1[l1]<q2[l2]) p=q1[l1++];
                        else p=q2[l2++];
                    }
                    ans=max(ans,(r-l+1)*(k-p));
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值