P2216 [HAOI2007]理想的正方形

原题链接

在二维上运用单调队列,我们可以想象在矩阵上移动滑动窗口,以左上角为起点,在在窗口内部我们对每一行求最值,再对每一列求最值,那么左上角的元素一定是最值,只需要将每个滑动窗口最值存储即可

没什么坑,有思路很快就能做出来

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1010;
 4 int c[N][N],tmpx[N][N],tmpX[N][N],q[N],Q[N];//求每一行n范围的最大值、最小值再对其求每一列的最值 
 5 int main()//以左上角坐标为基准 
 6 {
 7 //    freopen("in.txt","r",stdin);
 8     int a,b,n,ans = INT_MAX; 
 9     scanf("%d%d%d",&a,&b,&n);
10     for(int i=1;i<=a;i++)
11        for(int j=1;j<=b;j++)
12           scanf("%d",&c[i][j]);
13     for(int i=1;i<=a;i++){
14         int tt = -1,TT = -1,hh = 0,HH = 0;
15         for(int j=1;j<=b;j++){
16             while(hh<=tt&&q[hh]<j-n+1) ++hh;
17             while(HH<=TT&&Q[HH]<j-n+1) ++HH;
18             while(hh<=tt&&c[i][q[tt]]>=c[i][j]) --tt;
19             while(HH<=TT&&c[i][Q[TT]]<=c[i][j]) --TT;
20             q[++tt] = j; Q[++TT] = j;
21             if(j-n+1>0){
22                 tmpx[i][j-n+1] = c[i][q[hh]];
23                 tmpX[i][j-n+1] = c[i][Q[HH]];//对应每一个滑动窗口行的最值 
24             }
25         }
26     }
27     for(int j=1;j<=b-n+1;j++){
28         int tt = -1,TT = -1,hh = 0,HH = 0;
29         for(int i=1;i<=a;i++){
30             while(hh<=tt&&q[hh]<i-n+1) ++hh;
31             while(HH<=TT&&Q[HH]<i-n+1) ++HH;
32             while(hh<=tt&&tmpx[q[tt]][j]>=tmpx[i][j]) --tt;
33             while(HH<=TT&&tmpX[Q[TT]][j]<=tmpX[i][j]) --TT;
34             q[++tt] = i; Q[++TT] = i;
35             if(i-n+1>0){ 
36                 tmpx[i-n+1][j] = tmpx[q[hh]][j];
37                 tmpX[i-n+1][j] = tmpX[Q[HH]][j];//对应每一个滑动窗口行的最值 
38             }
39         }
40     }
41     for(int i=1;i<=a-n+1;i++)
42         for(int j=1;j<=b-n+1;j++)
43             ans = min(ans,tmpX[i][j]-tmpx[i][j]);
44     printf("%d\n",ans);
45     return 0; 
46 }

 

posted @ 2020-12-29 13:57  acmloser  阅读(108)  评论(0编辑  收藏  举报