• 2019牛客暑期多校训练营(第三场) F Planting Trees(单调队列+最大子矩阵)


    代码里面已经注释,复杂度可看成O($n^{3}$)

    AC代码:

     1 #include<bits/stdc++.h>
     2 #define numm ch-48
     3 #define pd putchar(' ')
     4 #define pn putchar('
    ')
     5 #define pb push_back
     6 #define mp make_pair
     7 #define fi first
     8 #define se second
     9 #define fi first
    10 #define se second
    11 #define fre1 freopen("1.txt","r",stdin)
    12 #define fre2 freopen("2.txt","w",stdout)
    13 using namespace std;
    14 template <typename T>
    15 void read(T &res) {
    16     bool flag=false;char ch;
    17     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    18     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    19     flag&&(res=-res);
    20 }
    21 template <typename T>
    22 void write(T x) {
    23     if(x<0) putchar('-'),x=-x;
    24     if(x>9) write(x/10);
    25     putchar(x%10+'0');
    26 }
    27 const int maxn=510;
    28 typedef long long ll;
    29 typedef long double ld;
    30 const ll mod=1e9+7;
    31 const int inf=0x3f3f3f3f;
    32 int que[maxn][2];
    33 ///2个单调队列,第二维0:维护单调递减的max下标,1:维护单调递增的min下标
    34 int a[maxn][maxn];
    35 int mx[maxn],mn[maxn];
    36 ///分别记录每一列的最大值和最小值
    37 int main()
    38 {
    39     int _;
    40     read(_);
    41     while(_--) {
    42         int n,k;
    43         read(n),read(k);
    44         for(int i=1;i<=n;i++)
    45             for(int j=1;j<=n;j++)
    46                 read(a[i][j]);
    47         int ans=1;
    48         for(int i=1;i<=n;i++) {     ///从i到j这段区间找最大子矩阵
    49             for(int j=1;j<=n;j++) { ///记录每列对应的最大值最小值
    50                 mx[j]=-inf;
    51                 mn[j]=inf;
    52             }
    53             for(int j=i;j<=n;j++) {
    54                 for(int r=1;r<=n;r++) { ///枚举当前行对应的每一列
    55                     mx[r]=max(mx[r],a[j][r]);
    56                     mn[r]=min(mn[r],a[j][r]);
    57                 }
    58                 int head0=1,tail0=0,head1=1,tail1=0,l=1;///l:从第i到第j行可行的左边界开始
    59                 for(int r=1;r<=n;r++) { ///枚举第i到第j行可行的右边界,左上角坐标(i,l),右下角坐标(j,r)
    60                     while(head0<=tail0&&mx[r]>=mx[que[tail0][0]])///单调递减
    61                         tail0--;
    62                     while(head1<=tail1&&mn[r]<=mn[que[tail1][1]])///单调递增
    63                         tail1--;
    64                     que[++tail0][0]=r;
    65                     que[++tail1][1]=r;
    66                     while(l<=r&&mx[que[head0][0]]-mn[que[head1][1]]>k) {
    67                         l++;
    68                         if(que[head0][0]<l) head0++;
    69                         if(que[head1][1]<l) head1++;
    70                     }
    71                     ans=max(ans,(j-i+1)*(r-l+1));
    72                 }
    73             }
    74         }
    75         write(ans);pn;
    76     }
    77     return 0;
    78 }
    View Code
  • 相关阅读:
    【Head First Servlets and JSP】笔记3:Servlet的生命周期
    正则表达
    【Java Web】把逻辑名映射到servlet文件
    【Head First Servlets and JSP】笔记2:MVC迷你教程
    【算法(第4版)】笔记
    【Head First Servlets and JSP】笔记1
    【python】对象和面向对象
    【深度探索c++对象模型】Function语义学之成员函数调用方式
    【c++】多重继承与虚继承
    【Scrapy】Selectors
  • 原文地址:https://www.cnblogs.com/wuliking/p/11253028.html
Copyright © 2020-2023  润新知