zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第三场)- F Planting Trees

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

    题意:给定n×n的矩阵,求最大子矩阵使得子矩阵中最大值和最小值的差值<=M。

    思路:先看数据大小,注意题目说所有样例的N^3不超过25e7,意思就是我们可以用O(n^3)过题。

       最大子矩阵第二场出现过,做法是枚举上下边界实现降维,同时我们维护每一列的最大值最小值,然后枚举右边界,这时候复杂度已经为O(n^3)。那么左边界怎么确定呢?我们用两个单调队列维护子矩阵的最大值最小值,根据题目条件确定左边界,注意代码37、38行是if不是while(我想了好久。。QAQ),因为最多只需要从队首出一次(也就是将head+1,这个仔细想想就明白),用while没必要,而且while会出现段错误,如果这时候l=k,加一之后l=k+1,head1会超出tail,而里面的值不确定,可能导致死循环。

       总复杂度为O(n^3)。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int maxn=505;
    
    int T,n,M,l,head1,tail1,head2,tail2,ans;
    int a[maxn][maxn],Ma[maxn],Mi[maxn];
    int q1[maxn],q2[maxn];
    
    int main(){
        scanf("%d",&T);
        while(T--){
            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 i=1;i<=n;++i){
                for(int k=1;k<=n;++k)
                    Ma[k]=Mi[k]=a[i][k];
                for(int j=i;j<=n;++j){
                    for(int k=1;k<=n;++k){
                        Ma[k]=max(Ma[k],a[j][k]);
                        Mi[k]=min(Mi[k],a[j][k]);
                    }
                    l=1,head1=head2=1,tail1=tail2=0;
                    for(int k=1;k<=n;++k){            
                        while(tail1>=head1&&Ma[q1[tail1]]<=Ma[k])
                            --tail1;
                        while(tail2>=head2&&Mi[q2[tail2]]>=Mi[k])
                            --tail2;
                        q1[++tail1]=k;
                        q2[++tail2]=k;
                        while(l<=k&&Ma[q1[head1]]-Mi[q2[head2]]>M){
                            ++l;
                            if(q1[head1]<l) ++head1;
                            if(q2[head2]<l) ++head2;
                        }
                        ans=max(ans,(j-i+1)*(k-l+1));
                    }
                }
            } 
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    Java实现 LeetCode 437 路径总和 III(三)
    Java实现 LeetCode 436 寻找右区间
    Java实现 LeetCode 436 寻找右区间
    Java实现 LeetCode 436 寻找右区间
    Java实现 LeetCode 435 无重叠区间
    Java实现 LeetCode 435 无重叠区间
    Makefile第一讲:一个简单的Makefile
    GCC常用参数
    GCC参数详解
    linux .o,.a,.so文件解析
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11272891.html
Copyright © 2011-2022 走看看