BZOJ1047: [HAOI2007]理想的正方形

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 3448  Solved: 1894
[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

Sample Output

1
 

思路{直接二维ST表就可以了,SB的我之前以为4个ST表,打完发现一个就可以了.}

 

#include<bits/stdc++.h>
#define RG register
#define il inline
#define LEN (1<<(k-1))
#define Inf (1<<30)
#define N 1001
using namespace std;
int rd[10][N][N][2];
int b[N][N],n,m,len,lim;
int max(int a,int b,int c,int d){a=max(a,b);c=max(c,d),a=max(a,c);return a;}
int min(int a,int b,int c,int d){a=min(a,b),c=min(c,d),a=min(a,c);return a;}
void Modify(int x,int y,int &X){
  int Max=max(rd[lim][x][y][1],rd[lim][x+len-(1<<lim)][y][1],
          rd[lim][x][y+len-(1<<lim)][1],rd[lim][x+len-(1<<lim)][y+len-(1<<lim)][1]);
  int Min=min(rd[lim][x][y][0],rd[lim][x+len-(1<<lim)][y][0],
          rd[lim][x][y+len-(1<<lim)][0],rd[lim][x+len-(1<<lim)][y+len-(1<<lim)][0]);
  X=min(X,Max-Min);
}
int main(){
  scanf("%d%d%d",&n,&m,&len);
  for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){
      scanf("%d",&b[i][j]);
      rd[0][i][j][0]=rd[0][i][j][1]=b[i][j];
    }
  for(lim=0;(1<<lim)<=len;++lim);lim--;
  for(int k=1;k<=lim;++k){
    for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){
    if(i+(1<<k)<=n+1&&j+(1<<k)<=m+1){
      rd[k][i][j][1]=max(rd[k-1][i][j][1],rd[k-1][i+LEN][j][1],rd[k-1][i][j+LEN][1],rd[k-1][i+LEN][j+LEN][1]);
      rd[k][i][j][0]=min(rd[k-1][i][j][0],rd[k-1][i+LEN][j][0],rd[k-1][i][j+LEN][0],rd[k-1][i+LEN][j+LEN][0]);
      }
      }
  }int Ans=Inf;for(int i=1;i+len-1<=n;++i)for(int j=1;j+len-1<=m;++j)Modify(i,j,Ans);
  cout<<Ans;
  return 0;
}

 

posted @ 2017-09-04 23:34  QYP_2002  阅读(105)  评论(0编辑  收藏  举报