[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 }