[BZOJ1047][HAOI2007]理想的正方形 二维单调队列

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1047

我们对每矩阵的一列维护一个大小为$n$的单调队列,队中元素为矩阵中元素。然后扫描每一行,再次维护一个大小为$n$的单调队列,队中元素为当前列的队列中取出的最值。$O(n^2)$扫过去就可以了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int INF=1<<30;
 6 int inline readint(){
 7     int Num;char ch;
 8     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
 9     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
10     return Num;
11 }
12 int A,B,N;
13 int M[1010][1010];
14 int qmn1[1010][1010],qmn2[1010][1010],hmn[1010],tmn[1010];
15 int qmx1[1010][1010],qmx2[1010][1010],hmx[1010],tmx[1010];
16 int Qmn1[1010],Qmn2[1010],Hmn,Tmn;
17 int Qmx1[1010],Qmx2[1010],Hmx,Tmx;
18 int main(){
19     A=readint();
20     B=readint();
21     N=readint();
22     for(int i=1;i<=A;i++)
23         for(int j=1;j<=B;j++)
24             M[i][j]=readint();
25     for(int i=1;i<=B;i++){
26         hmx[i]=hmn[i]=1;
27         tmx[i]=tmn[i]=0;
28         for(int j=1;j<N;j++){
29             while(hmx[i]<=tmx[i]&&qmx1[i][tmx[i]]<=M[j][i]) tmx[i]--;
30             qmx1[i][++tmx[i]]=M[j][i];
31             qmx2[i][tmx[i]]=j;
32             while(hmn[i]<=tmn[i]&&qmn1[i][tmn[i]]>=M[j][i]) tmn[i]--;
33             qmn1[i][++tmn[i]]=M[j][i];
34             qmn2[i][tmn[i]]=j;
35         }
36     }
37     int ans=INF;
38     for(int i=N;i<=A;i++){
39         for(int j=1;j<=B;j++){
40             while(hmx[j]<=tmx[j]&&qmx2[j][hmx[j]]+N<=i) hmx[j]++;
41             while(hmx[j]<=tmx[j]&&qmx1[j][tmx[j]]<=M[i][j]) tmx[j]--;
42             qmx1[j][++tmx[j]]=M[i][j];
43             qmx2[j][tmx[j]]=i;
44             while(hmn[j]<=tmn[j]&&qmn2[j][hmn[j]]+N<=i) hmn[j]++;
45             while(hmn[j]<=tmn[j]&&qmn1[j][tmn[j]]>=M[i][j]) tmn[j]--;
46             qmn1[j][++tmn[j]]=M[i][j];
47             qmn2[j][tmn[j]]=i;
48         }    
49         Hmx=Hmn=1;
50         Tmx=Tmn=0;
51         for(int j=1;j<N;j++){
52             while(Hmx<=Tmx&&Qmx1[Tmx]<=qmx1[j][hmx[j]]) Tmx--;
53             Qmx1[++Tmx]=qmx1[j][hmx[j]];
54             Qmx2[Tmx]=j;
55             while(Hmn<=Tmn&&Qmn1[Tmn]>=qmn1[j][hmn[j]]) Tmn--;
56             Qmn1[++Tmn]=qmn1[j][hmn[j]];
57             Qmn2[Tmn]=j;
58         }
59         for(int j=N;j<=B;j++){
60             while(Hmx<=Tmx&&Qmx2[Hmx]+N<=j) Hmx++;
61             while(Hmx<=Tmx&&Qmx1[Tmx]<=qmx1[j][hmx[j]]) Tmx--;
62             Qmx1[++Tmx]=qmx1[j][hmx[j]];
63             Qmx2[Tmx]=j;
64             while(Hmn<=Tmn&&Qmn2[Hmn]+N<=j) Hmn++;
65             while(Hmn<=Tmn&&Qmn1[Tmn]>=qmn1[j][hmn[j]]) Tmn--;
66             Qmn1[++Tmn]=qmn1[j][hmn[j]];
67             Qmn2[Tmn]=j;
68             ans=min(ans,Qmx1[Hmx]-Qmn1[Hmn]);
69         }        
70     }
71     printf("%d\n",ans);
72     return 0;
73 }

 

posted @ 2017-10-10 20:44  halfrot  阅读(203)  评论(0编辑  收藏  举报