[BZOJ1047][HAOI2007]理想的正方形

1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2230  Solved: 1188
[Submit][Status][Discuss]

Description

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

Input

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

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

HINT

 

问题规模

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

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

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

 

Source

这个题有很多解法,我用了效率不高的二维不优化RMQ(呵呵能AC真是奇迹),具体就是用$maxm[i][j][k]$表示左上角是$(i,j)$,大小为$2^k*2^k$的正方形中的最大值,最小值同样处理。之后仿照一维情况,倍增预处理,注意使用 long long 。最后输出时枚举左上角位置,计算并输出,总的时间复杂度大概是$O(ablog n+ab)$。

/**************************************************************
    Problem: 1047
    User: bhiaib0gf
    Language: C++
    Result: Accepted
    Time:4420 ms
    Memory:110876 kb
****************************************************************/
 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define log2(x) (log(x)/log(2))
long long maxm[1001][1001][7],minm[1001][1001][7];
int a,b,n;
int readint()
{
    int ans=0;
    char c;
    while (!isdigit(c=getchar()));
    do
    {
        ans=ans*10+c-'0';
        c=getchar();    
    } while (isdigit(c));
    return ans;
}
int main()
{
    a=readint(),b=readint(),n=readint();
    for (int i=1;i<=a;i++)
        for (int j=1;j<=b;j++)
        {
            maxm[i][j][0]=readint();
            minm[i][j][0]=maxm[i][j][0];
        }
    for (int i1=1;i1<=log2(n);i1++)
    {
        for (int i=1;i+(1<<i1)-1<=a;i++)
            for (int j=1;j+(1<<i1)-1<=b;j++)
            {
                maxm[i][j][i1]=max(
                    max(
                        maxm[i][j][i1-1],
                        maxm[i+(1<<(i1-1))][j][i1-1]
                    ),
                    max(
                        maxm[i][j+(1<<(i1-1))][i1-1],
                        maxm[i+(1<<(i1-1))][j+(1<<(i1-1))][i1-1]
                    )
                );
                minm[i][j][i1]=min(
                    min(
                        minm[i][j][i1-1],
                        minm[i+(1<<(i1-1))][j][i1-1]
                    ),
                    min(
                        minm[i][j+(1<<(i1-1))][i1-1],
                        minm[i+(1<<(i1-1))][j+(1<<(i1-1))][i1-1]
                    )
                );
            }
    }
    long long ans=(1<<31);
    ans*=ans;
    for (int i=1;i+n-1<=a;i++)
        for (int j=1;j+n-1<=b;j++)
        {
            int ls=int(log2(n));
            int maxnumber=max(
                max(
                    maxm[i][j][ls],
                    maxm[i+n-(1<<ls)][j][ls]
                ),max(
                    maxm[i][j+n-(1<<ls)][ls],
                    maxm[i+n-(1<<ls)][j+n-(1<<ls)][ls]
                )
            );
            int minnumber=min(
                min(
                    minm[i][j][ls],
                    minm[i+n-(1<<ls)][j][ls]
                ),min(
                    minm[i][j+n-(1<<ls)][ls],
                    minm[i+n-(1<<ls)][j+n-(1<<ls)][ls]
                )
            );
            if (maxnumber-minnumber<ans)
                ans=maxnumber-minnumber;
        }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2015-11-24 21:45  常可  阅读(231)  评论(0编辑  收藏  举报