zoukankan      html  css  js  c++  java
  • 【DP专题】——洛谷P2216理想正方形

    强烈推荐这道单调队列好题!

    传送门:GO


    参考了一下这篇题解:GO

    对于点(i,j)

    两个单调队列,先以行为单位,求出长度为n的一段区间的最值(i,(j~j+n-1)),在此基础上,以列为单位,求出((i~i+n-1),(j~j+n-1))的最值。

    以n为3为例:

     先是这样的感觉,每个色条处理的是每块的最值。

     接着根据上面求出的结果,竖着来一次。

    最后就能得到每个点为左上角的n*n正方形的最值了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int read(){
     4     int x=0,f=1;
     5     char c=getchar();
     6     while(!isdigit(c)){
     7         if(c=='-') f=-1;
     8         c=getchar();
     9     }
    10     while(isdigit(c)){
    11         x=(x<<1)+(x<<3)+(c^48);
    12         c=getchar();
    13     }
    14     return x*f;
    15 }
    16 const int N=1e3+10;
    17 int a,b,n;
    18 int ma[N][N];
    19 int maxwh[N][N],maxn[N][N],minwh[N][N],minn[N][N];
    20 int que1[N<<1],que2[N<<1];
    21 int head1,tail1,head2,tail2;
    22 int main(){
    23     a=read();b=read();n=read();
    24     for(int i=1;i<=a;i++){
    25         for(int j=1;j<=b;j++){
    26             ma[i][j]=read();
    27         }
    28     }
    29     for(int i=1;i<=a;i++){
    30         head1=tail1=head2=tail2=que1[1]=que2[1]=1;
    31         for(int j=2;j<=b;j++){
    32             while(head1<=tail1&&ma[i][j]>=ma[i][que1[tail1]]) tail1--;
    33             while(head2<=tail2&&ma[i][j]<=ma[i][que2[tail2]]) tail2--;
    34             que1[++tail1]=j;
    35             que2[++tail2]=j;
    36             while(j-que1[head1]+1>n) head1++;
    37             while(j-que2[head2]+1>n) head2++;
    38             if(j>=n) maxwh[i][j-n+1]=ma[i][que1[head1]],minwh[i][j-n+1]=ma[i][que2[head2]]; 
    39         }
    40     }
    41     for(int i=1;i<=b-n+1;i++){
    42         head1=tail1=head2=tail2=que1[1]=que2[1]=1;
    43         for(int j=2;j<=a;j++){
    44             while(head1<=tail1&&maxwh[j][i]>=maxwh[que1[tail1]][i]) tail1--;
    45             while(head2<=tail2&&minwh[j][i]<=minwh[que2[tail2]][i]) tail2--;
    46             que1[++tail1]=j;
    47             que2[++tail2]=j;
    48             while(j-que1[head1]+1>n) head1++;
    49             while(j-que2[head2]+1>n) head2++;
    50             if(j>=n) maxn[j-n+1][i]=maxwh[que1[head1]][i],minn[j-n+1][i]=minwh[que2[head2]][i];
    51         }
    52     }
    53     int ans=1e9;
    54     for(int i=1;i<=a-n+1;i++){
    55         for(int j=1;j<=b-n+1;j++){
    56             ans=min(ans,maxn[i][j]-minn[i][j]);
    57         }
    58     }
    59     printf("%d",ans);
    60     return 0;
    61 } 
    ——抓住了时间,却不会利用的人,终究也逃不过失败的命运。
  • 相关阅读:
    Codeforces Round #161 (Div. 2)
    Codeforces Round #160 (Div. 2)
    Codeforces Round #159 (Div. 2)
    Codeforces Round #157 (Div. 2)
    世界树的考验「NOIP多校联考 2019」
    最大异或和
    腿部挂件「NOIP多校联考 2019」
    玩具取名「HAOI2008」
    涂色「CQOI2007」
    唱、跳、rap 和篮球「TJOI2019」
  • 原文地址:https://www.cnblogs.com/Nelson992770019/p/11599899.html
Copyright © 2011-2022 走看看