BZOJ 1047: [HAOI2007]理想的正方形
Fancy
posted @ 2015年7月08日 22:51
in BZOJ
, 333 阅读
题目大意:有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
横着一遍单调队列求最大最小值,再把求出来的在竖着求一遍,然后暴力统计答案
#include<iostream> #include<cstring> #include<cstdio> const int inf=1000000001; using namespace std; int g[1001],f[1001],max1[1001][1001],max2[1001][1001], min1[1001][1001],min2[1001][1001]; int n,m,T,num,ans=inf; int main() { scanf("%d%d%d",&n,&m,&T); for(int i=1;i<=n;i++) { num=0; memset(g,-1,sizeof(g)); for(int j=1;j<=m;j++) f[j]=inf; for(int j=1,x;j<=m;j++) { scanf("%d",&x); int a=num,b=num; while(g[a]<=x&&i>0) g[a]=-1,a--; while(f[b]>=x&&i>0) f[b]=inf,b--; g[++num]=x;f[num]=x; if(j>=T) { for(int a=j-T+1;a<=j;a++) if(g[a]>=0) {max1[i][j-T+1]=g[a];break;} for(int a=j-T+1;a<=j;a++) if(f[a]<inf) {min1[i][j-T+1]=f[a];break;} } } } for(int i=1;i<=m-T+1;i++) { num=0; memset(g,-1,sizeof(g)); for(int j=1;j<=n;j++) f[j]=inf; for(int j=1;j<=n;j++) { int x=max1[j][i],y=min1[j][i]; int a=num,b=num; while(g[a]<=x&&i>0) g[a]=-1,a--; while(f[b]>=y&&i>0) f[b]=inf,b--; g[++num]=x;f[num]=y; if(j>=T) { for(int a=j-T+1;a<=j;a++) if(g[a]>=0) {max2[j-T+1][i]=g[a];break;} for(int a=j-T+1;a<=j;a++) if(f[a]<inf) {min2[j-T+1][i]=f[a];break;} } } } for(int i=1;i<=n-T+1;i++) for(int j=1;j<=m-T+1;j++) ans=min(ans,max2[i][j]-min2[i][j]); printf("%d",ans); }