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);
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter