洛谷P2216 [HAOI2007] 理想的正方形
题目描述
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
输入输出格式
输入格式:
第一行为3个整数,分别表示a,b,n的值
第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
输出格式:
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
输入输出样例
输入样例#1:
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
输出样例#1:
1
说明
问题规模
(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
跑两遍DP,第一遍处理出行i内以j为端点的长度为n的区间内的最大值和最小值。
第二遍DP,根据之前处理出的一维区间最值,DP出二维区间最值。
然后枚举区间端点,找最优解。
需要用单调队列优化
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=1010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 int mp[mxn][mxn]; 17 int fmx[mxn][mxn],fmi[mxn][mxn]; 18 int dpmx[mxn][mxn],dpmi[mxn][mxn]; 19 int a,b,n; 20 void work(){ 21 22 } 23 int q1[mxn],hd1=0,tl1=0; 24 int q2[mxn],hd2=0,tl2=0; 25 int main(){ 26 a=read();b=read();n=read(); 27 int i,j; 28 memset(fmi,0x3f,sizeof fmi); 29 for(i=1;i<=a;i++){ 30 hd1=hd2=1; 31 tl1=tl2=0; 32 for(j=1;j<=b;j++){ 33 mp[i][j]=read(); 34 while(hd1<=tl1 && j-q1[hd1]>=n)hd1++; 35 while(hd1<=tl1 && mp[i][j]>=mp[i][q1[tl1]]) tl1--; 36 q1[++tl1]=j; 37 fmx[i][j]=mp[i][q1[hd1]]; 38 //max 39 while(hd2<=tl2 && j-q2[hd2]>=n)hd2++; 40 while(hd2<=tl2 && mp[i][j]<=mp[i][q2[tl2]]) tl2--; 41 q2[++tl2]=j; 42 fmi[i][j]=mp[i][q2[hd2]]; 43 //min 44 } 45 } 46 memset(dpmi,0x3f,sizeof dpmi); 47 hd1=hd2=1;tl1=tl2=0; 48 for(j=1;j<=b;j++){ 49 hd1=hd2=1;tl1=tl2=0; 50 for(i=1;i<=a;i++){ 51 while(hd1<=tl1 && i-q1[hd1]>=n)hd1++; 52 while(hd1<=tl1 && fmx[i][j]>=fmx[q1[tl1]][j])tl1--; 53 q1[++tl1]=i; 54 dpmx[i][j]=fmx[q1[hd1]][j]; 55 56 while(hd2<=tl2 && i-q2[hd2]>=n)hd2++; 57 while(hd2<=tl2 && fmi[i][j]<=fmi[q2[tl2]][j])tl2--; 58 q2[++tl2]=i; 59 dpmi[i][j]=fmi[q2[hd2]][j]; 60 61 } 62 } 63 int ans=0x3f3f3f3f; 64 for(i=n;i<=a;i++) 65 for(j=n;j<=b;j++){ 66 ans=min(ans,dpmx[i][j]-dpmi[i][j]); 67 } 68 printf("%d\n",ans); 69 return 0; 70 }
本文为博主原创文章,转载请注明出处。