理想的正方形 HAOI2007(二维RMQ)

理想的正方形

 

省队选拔赛河南

 时间限制: 1 s
 空间限制: 256000 KB
 题目等级 : 大师 Master
 
 
 
题目描述 Description

    有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

输入描述 Input Description

    第一行为3个整数,分别表示a,b,n的值

    第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。

输出描述 Output Description

 仅一个整数,为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

数据范围及提示 Data Size & Hint

(1)矩阵中的所有数都不超过1,000,000,000

(2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10

(3)100%的数据2<=a,b<=1500,n<=a,n<=b,n<=100

 

/*
嗯,脑补二维RMQ fail,挂成暴力分。
一维是维护一个区间,二维是维护一个矩阵。
由于这个题是小正方形,三维数组即可。二维RMQ略麻烦... 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>

#define x2 x1+n-1-(1<<m)+1
#define y2 y1+n-1-(1<<m)+1

using namespace std;
void read(int &x)
{
    int f=1;x=0;char c=getchar();
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    x*=f;
}

void out(int x)
{
    if(!x){putchar('0');return;}
    if(x<0){x=~x+1;putchar('-');}
    char c[30]= {0};
    while(x)c[++c[0]]=x%10+48,x/=10;
    while(c[0])putchar(c[c[0]--]);
}
const int inf=1e3+29;
int i,j,k,m;
int g[inf][inf][12];
int f[inf][inf][12];
int x,y,n;
int ans=0x7fffffff;

int query(int x1,int y1)
{
    int maxn=0,minn=0x7fffffff;
    maxn=max(f[x1][y1][m],f[x2][y2][m]);
    maxn=max(maxn,f[x1][y2][m]);
    maxn=max(maxn,f[x2][y1][m]);
    minn=min(g[x1][y1][m],g[x2][y2][m]);
    minn=min(minn,g[x1][y2][m]);
    minn=min(minn,g[x2][y1][m]);
    return maxn-minn;
}

int main()
{
    read(y);read(x);
    read(n);m=log(n)/log(2);
    for(i=1; i<=y; i++)
      for(j=1; j<=x; j++)
        {
            read(f[j][i][0]);
            g[j][i][0]=f[j][i][0];
        }
    for(k=1; k<=12; k++)
      for(i=1; i+(1<<k)-1<=x; i++)
        for(j=1; j+(1<<k)-1<=y; j++)
        {
            f[i][j][k]=max(f[i][j][k-1],f[i+(1<<(k-1))][j+(1<<(k-1))][k-1]);
            f[i][j][k]=max(f[i][j][k],f[i+(1<<(k-1))][j][k-1]);
            f[i][j][k]=max(f[i][j][k],f[i][j+(1<<(k-1))][k-1]);
            g[i][j][k]=min(g[i][j][k-1],g[i+(1<<(k-1))][j+(1<<(k-1))][k-1]);
            g[i][j][k]=min(g[i][j][k],g[i+(1<<(k-1))][j][k-1]);
            g[i][j][k]=min(g[i][j][k],g[i][j+(1<<(k-1))][k-1]);
        }
    for(i=1; i+n-1<=x; i++)
      for(j=1; j+n-1<=y; j++)
        ans=min(ans,query(i,j));
    out(ans);
    return 0;
}

 

posted @ 2017-10-23 21:40  安月冷  阅读(186)  评论(0编辑  收藏  举报