BZOJ 1047 [HAOI2007]理想的正方形
1047: [HAOI2007]理想的正方形
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2054 Solved: 1091
[Submit][Status][Discuss]
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
Output
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
Sample Input
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
Sample Output
1
HINT
问题规模
(1)矩阵中的所有数都不超过1,000,000,000
(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10
(3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
Source
题解:太神了,膜郑爷%%%
首先看数据范围,很显然要求线性算法,那就是说只能扫一次喽,那就是说要O(1)维护喽,那就是说要敲单调队列喽。。。
既然要写moque,就要着重考虑一下啥时候该删除了。首先把窝萌的查询的框分成4部分:
假设窝萌的小正方形从左上角往下动,那么很显然1区域对于两个方向只是添加,2区域对于y方向是增加,对于x方向是维护,3区域对于x方向是增加,对于y方向是维护,4区域对于两个方向都是维护。
那就好办呀,对于不同的部分用不同的办法维护不就好了。。。。
注意这里有个细节:比如窝萌维护1区域的时候一定是1~n-1!!!为啥?因为i=n的时候就需要开始回答了!
然后说一下单调队列:窝萌还需要记录一下进队的时间,用来维护pop操作。然后就码就行了。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<stack> 6 #include<queue> 7 #include<cstring> 8 #define PAU putchar(' ') 9 #define ENT putchar('\n') 10 using namespace std; 11 const int maxn=1000+10,inf=-1u>>1; 12 struct moque{ 13 int a1[1001],t1[1001],a2[1001],t2[1001]; 14 int st1,ed1,st2,ed2; 15 moque(){st1=1;ed1=0;st2=1;ed2=0;} 16 void pushmi(int x,int t){ 17 while((st1<=ed1)&&(x<=a1[ed1]))ed1--;ed1++;a1[ed1]=x;t1[ed1]=t;return; 18 } 19 void pushmx(int x,int t){ 20 while((st2<=ed2)&&(x>=a2[ed2]))ed2--;ed2++;a2[ed2]=x;t2[ed2]=t;return; 21 } 22 void pop(int t){ 23 if(t1[st1]==t)st1++;if(t2[st2]==t)st2++;return; 24 } 25 int qmin(){return a1[st1];} 26 int qmax(){return a2[st2];} 27 }qx[maxn],qy[maxn]; 28 int a,b,n,A[maxn][maxn]; 29 inline int read(){ 30 int x=0,sig=1;char ch=getchar(); 31 for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0; 32 for(;isdigit(ch);ch=getchar())x=10*x+ch-'0'; 33 return sig?x:-x; 34 } 35 inline void write(int x){ 36 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 37 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 38 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 39 } 40 int main(){ 41 a=read();b=read();n=read(); 42 for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)A[i][j]=read(); 43 for(int i=1;i<n;i++){ 44 for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j); 45 for(int j=n;j<=b;j++){ 46 qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j); 47 qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i); 48 qx[i].pop(j-n+1); 49 } 50 }int ans=inf; 51 for(int i=n;i<=a;i++){ 52 for(int j=1;j<n;j++)qx[i].pushmi(A[i][j],j),qx[i].pushmx(A[i][j],j); 53 for(int j=n;j<=b;j++){ 54 qx[i].pushmi(A[i][j],j);qx[i].pushmx(A[i][j],j); 55 qy[j].pushmi(qx[i].qmin(),i);qy[j].pushmx(qx[i].qmax(),i); 56 ans=min(ans,qy[j].qmax()-qy[j].qmin()); 57 qx[i].pop(j-n+1);qy[j].pop(i-n+1); 58 } 59 }write(ans); 60 return 0; 61 }