More than 2019 cattle off summer school camp (third) - F Planting Trees

Topic link: https: //ac.nowcoder.com/acm/contest/883/F

The meaning of problems: Given an n × n matrix, seeking the most sub-matrix so that the sub-matrix of the difference between the maximum value and the minimum value <= M.

Idea: look at the data size, pay attention to the subject say that all samples of N ^ 3 does not exceed 25e7, it means that we can use O (n ^ 3) had problems.

   The second largest sub-matrix field appeared, approach is to enumerate the upper and lower boundaries to achieve dimensionality reduction, while we maintain the maximum minimum value of each column, and then enumerate the right boundary, this time complexity is already O (n ^ 3). So how to determine the left edge of it? We use two queues monotonous maximum minimum maintenance sub-matrices to determine the left boundary conditions based on the topic, pay attention to the line of code is 37, 38 if not while (I think for a long time ..QAQ), because most just from the first team out once (that is, the head + 1, will understand this think about it), while no need to use, and while mistakes will occur, if this time l = k, plus one after l = k + 1, head1 exceed the tail, the value of the uncertainty which may result in an infinite loop.

   The total complexity is O (n ^ 3).

AC Code:

#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\n",ans);
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/FrankChen831X/p/11272891.html