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

题意:给你一个n*n的高度矩阵 要你找到里面最大的矩阵且最大的高度差不能超过m

思路:我们首先枚举上下右边界,然后我们可以用单调队列维护一个最左的边界 然后计算最大值 时间复杂度为O(n*n*n)

#include<bits/stdc++.h>
#define ll long long
const int inf = 0x3f3f3f3f;
const int N = 507;
const ll mod = 998244353;
using namespace std;
int a[N][N];
int q1[N],q2[N],minn[N],maxx[N];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t; cin>>t;
    while(t--){
        int n,m; cin>>n>>m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                cin>>a[i][j];
        int ans=0;
        for(int i=1;i<=n;i++){
            memset(maxx,-1,sizeof(maxx));
            memset(minn,inf,sizeof(minn));
            for(int j=i;j<=n;j++){
                for(int k=1;k<=n;k++){
                    maxx[k]=max(maxx[k],a[j][k]);
                    minn[k]=min(minn[k],a[j][k]);
                }
                int l1,l2,r1,r2;
                l1=l2=1; r1=r2=0;
                int po=1;
                for(int k=1;k<=n;k++){
                    while(l1<=r1&&maxx[k]>=maxx[q1[r1]]) --r1;
                    q1[++r1]=k;
                    while(l2<=r2&&minn[k]<=minn[q2[r2]]) --r2;
                    q2[++r2]=k;
                    while(l1<=r1&&l2<=r2&&maxx[q1[l1]]-minn[q2[l2]]>m){
                        po=min(q1[l1]+1,q2[l2]+1);
                        while(l1<=r1&&q1[l1]<po)
                            ++l1;
                        while(l2<=r2&&q2[l2]<po)
                            ++l2;
                    }
                    ans=max(ans,(j-i+1)*(k-po+1));
                }
            }
        }
        cout<<ans<<endl;
    } 
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wmj6/p/11249823.html