牛客暑期训练第三场F-Planting Trees (单调队列)

题目:https://ac.nowcoder.com/acm/contest/883/F

题意:找最大的矩阵,满足矩阵内最大值最小值差值不超过m。

思路:n<=500,可以O(n^3)先确定上、下、右边界,问题转化为一维数组中O(1)找出最远左边界。记录以当前坐标为右边界时的最大值和最小值,两个单调队列维护最大值递减,最小值递增,每次找队尾的满足条件的一对最大值和最小值,更新答案即可。

代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 502;
const int inf = 1e9;
int t, n, m, a[maxn][maxn], l1, r1, l2, r2, q1[maxn], q2[maxn], p, mx[maxn], mn[maxn];
int main()
{
    scanf("%d", &t);
    while(t--){
        int ans = 0;
        scanf("%d%d", &n, &m);
        for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) scanf("%d", &a[i][j]);

        for(int u=1; u<=n; u++){//up
            memset(mx, 0, sizeof mx); memset(mn, 0x3f, sizeof mn);
            for(int d=u; d<=n; d++){//down
                l1 = r1 = l2 = r2 = 0;
                for(int r=1,p=0; r<=n; r++){//right
                    mx[r]=max(mx[r], a[d][r]), mn[r]=min(mn[r], a[d][r]);
                    while(l1<r1&&mx[q1[r1-1]]<mx[r]) r1--;
                    while(l2<r2&&mn[q2[r2-1]]>mn[r]) r2--;
                    q1[r1++] = q2[r2++] = r;
                    while(l1<r1&&l2<r2&&mx[q1[l1]]-mn[q2[l2]]>m)
                        p = q1[l1]<q2[l2] ? q1[l1++] : q2[l2++];
                    ans = max(ans, (d-u+1)*(r-p));
                }
            }
        }
        cout << ans << endl;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值