BZOJ 1047
1047: [HAOI2007]理想的正方形
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3686 Solved: 2037
[Submit][Status][Discuss]
Description
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
Input
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=1000
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
好久没写题了。。。
我可是要冲省队的呀!!!
这道题嘛就二维单调队列,理解起来并不难
先搞定一维的再加另一重循环应该能减少调试时间(可惜我没有意识到调了半天)
另外按列来看的时候要注意分清到底是哪一维再操作
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define N 1005 using namespace std; int a,b,n,lmax=1,rmax,lmin=1,rmin; int m[N][N],qmax[N],qmin[N],tmax[N][N],tmin[N][N],amax[N][N],amin[N][N]; int main() { scanf("%d%d%d",&a,&b,&n); for(int i=1;i<=a;i++) for(int j=1;j<=b;j++) scanf("%d",&m[i][j]); for(int i=1;i<=a;i++) { lmax=1;rmax=0; memset(qmax,0,sizeof(qmax)); for(int j=1;j<=b;j++) { while(lmax<=rmax && qmax[lmax]<=j-n)lmax++; while(lmax<=rmax && m[i][j]>=m[i][qmax[rmax]])rmax--; qmax[++rmax]=j;tmax[i][j]=m[i][qmax[lmax]]; } /* for(int k=1;k<=a;k++)printf("%d ",tmax[i][k]); printf("\n"); */ lmin=1;rmin=0; memset(qmin,0,sizeof(qmin)); for(int j=1;j<=b;j++) { while(lmin<=rmin && qmin[lmin]<=j-n)lmin++; while(lmin<=rmin && m[i][j]<=m[i][qmin[rmin]])rmin--; qmin[++rmin]=j;tmin[i][j]=m[i][qmin[lmin]]; } } /* printf("\n"); for(int i=1;i<=a;i++) { for(int j=1;j<=b;j++) printf("%d ",tmax[i][j]); printf("\n"); } printf("\n"); for(int i=1;i<=a;i++) { for(int j=1;j<=b;j++) printf("%d ",tmin[i][j]); printf("\n"); } */ for(int i=1;i<=b;i++) { lmax=1;rmax=0; memset(qmax,0,sizeof(qmax)); for(int j=1;j<=a;j++) { while(lmax<=rmax && qmax[lmax]<=j-n)lmax++; while(lmax<=rmax && tmax[j][i]>=tmax[qmax[rmax]][i])rmax--; qmax[++rmax]=j;amax[j][i]=tmax[qmax[lmax]][i]; } /* for(int k=1;k<=a;k++)printf("%d ",amax[k][i]); printf("\n"); */ lmin=1;rmin=0; memset(qmin,0,sizeof(qmin)); for(int j=1;j<=a;j++) { while(lmin<=rmin && qmin[lmin]<=j-n)lmin++; while(lmin<=rmin && tmin[j][i]<=tmin[qmin[rmin]][i])rmin--; qmin[++rmin]=j;amin[j][i]=tmin[qmin[lmin]][i]; } } /* printf("\n"); for(int i=1;i<=a;i++) { for(int j=1;j<=b;j++) printf("%d ",amax[i][j]); printf("\n"); } printf("\n"); for(int i=1;i<=a;i++) { for(int j=1;j<=b;j++) printf("%d ",amin[i][j]); printf("\n"); } */ int ans=1000000000; for(int i=n;i<=a;i++) for(int j=n;j<=b;j++) ans=min(ans,amax[i][j]-amin[i][j]); printf("%d",ans); // system("pause"); return 0; }