• 【单调队列】bzoj 1407 [HAOI2007]理想的正方形


    【题意】

    • 给定一个n*m的矩阵,求所有大小为k*k的正方形中(最大值-最小值)的最小值

    【思路】

    • 先横着算出每一行的长度为k的窗口内的最大值,变成一个n*(m-k+1)的矩阵mx
    • 再竖着算出每一列的长度为k的窗口内的最大值,变成一个(n-k+1)*(m-k+1)的矩阵t1(在mx的基础上算)
    • 问题到这里转化为裸的单调队列
    • 最小值同理
    • 时间复杂度为O(n*m)
    • 转自http://www.cnblogs.com/szy-wlxy/p/4631700.html

    【AC】

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 inline int read()
      5 {
      6     int x=0,f=1;char ch=getchar();
      7     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
      8     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
      9     return x*f;
     10 }
     11 
     12 int n,m,k;
     13 const int maxn=1e3+2;
     14 int a[maxn][maxn];
     15 int mx[maxn][maxn];
     16 int mn[maxn][maxn];
     17 int t1[maxn][maxn];
     18 int t2[maxn][maxn];
     19 struct node
     20 {
     21     int x;
     22     int pos;
     23     node(){}
     24     node(int _x,int _pos):x(_x),pos(_pos){}
     25 }q[maxn];
     26 void pre()
     27 {
     28     for(int i=1;i<=n;i++)
     29     {
     30         //max 
     31         int head=1,tail=0;
     32         for(int j=1;j<=m;j++)
     33         {
     34             while(tail>=head&&q[tail].x<=a[i][j])
     35                  tail--;
     36             q[++tail].x=a[i][j],q[tail].pos=j;
     37             while(q[head].pos<=j-k)
     38                  head++;
     39             if(j>=k) 
     40                 mx[i][j]=q[head].x;
     41         }
     42         //min
     43         head=1,tail=0;
     44         for(int j=1;j<=m;j++)
     45         {
     46             while(tail>=head&&q[tail].x>=a[i][j])
     47                  tail--;
     48             q[++tail].x=a[i][j],q[tail].pos=j;
     49             while(q[head].pos<=j-k)
     50                  head++;
     51             if(j>=k) 
     52                 mn[i][j]=q[head].x;
     53         }
     54     }
     55 }
     56 void solve()
     57 {
     58     for(int j=k;j<=m;j++)
     59     {
     60         int head=1,tail=0;
     61         for(int i=1;i<=n;i++)
     62         {
     63             while(tail>=head&&q[tail].x<=mx[i][j])
     64                  tail--;
     65             q[++tail].x=mx[i][j],q[tail].pos=i;
     66             while(q[head].pos<=i-k)
     67                  head++;
     68             if(i>=k) 
     69                 t1[i][j]=q[head].x;
     70         }
     71     }
     72     for(int j=k;j<=m;j++)
     73     {
     74         int head=1,tail=0;
     75         for(int i=1;i<=n;i++)
     76         {
     77             while(tail>=head&&q[tail].x>=mn[i][j])
     78                  tail--;
     79             q[++tail].x=mn[i][j],q[tail].pos=i;
     80             while(q[head].pos<=i-k)
     81                  head++;
     82             if(i>=k) 
     83                 t2[i][j]=q[head].x;
     84         }
     85     }
     86     int ans;
     87     for(int i=k;i<=n;i++)
     88     {
     89         for(int j=k;j<=m;j++)
     90         {
     91             if(i==k&&j==k) ans=t1[i][j]-t2[i][j];
     92             else ans=min(ans,t1[i][j]-t2[i][j]);    
     93         }
     94     }
     95     printf("%d
    ",ans);
     96 }
     97 int main()
     98 {
     99     n=read();m=read();k=read();
    100     for(int i=1;i<=n;i++)
    101     {
    102         for(int j=1;j<=m;j++)
    103         {
    104             a[i][j]=read();
    105         }
    106     }
    107     pre();
    108     solve();
    109     return 0;
    110 }
    单调队列
  • 相关阅读:
    jquery-4 完整表单验证实例
    从程序员的角度分析微信小程序(编程语言:用到什么学什么)
    微信程序开发
    css3-4 css3边框样式
    css3-3 css3背景样式
    boxfilter 实现
    opencv在arm和x86在移植
    PAT 1033. To Fill or Not to Fill (贪婪)
    [git] fatal: This operation must be run in a work tree
    spring与mybatis集成和事务控制
  • 原文地址:https://www.cnblogs.com/itcsl/p/7443604.html
Copyright © 2020-2023  润新知