[HNOI2007] 理想正方形 二维ST表

题目描述

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

输入输出格式

输入格式:

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

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

输出格式:

仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。

输入输出样例

输入样例#1: 
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
输出样例#1: 
1

说明

问题规模

(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

 


 

 

直接线段树搞貌似不太现实...

学了学二维ST表,没学会,先留着坑,以后学

 


 

 

#include 
#include 
#include 
using namespace std;
int a, b, n;
int tt;
int STn[1001][1001];
int STx[1001][1001]; 
int G[1001][1001];
int ans = 0x7f7f7f7f;

inline int Query(int x, int y)
{
    int maxx = 0, minn = 0;
    maxx = max(STx[x][y], max(STx[x - (1<1<1<1< n]))) ;
    minn = min(STn[x][y], min(STn[x - (1<1<1<1< n]))) ;
    return maxx - minn;
}

int main()
{
    scanf("%d%d%d", &a, &b, &n);
    tt = log(n) / log(2);
    for (register int i = 1 ; i <= a ; i ++)
    {
        for (register int j = 1 ; j <= b ; j ++)
        {
            int x;scanf("%d", &x);G[i][j] = x;
            STn[i][j] = STx[i][j] = x;
        }
    }
    for (register int k = 0 ; k < tt ; k ++)
    {
        for (register int i = 1 ; i <= a ; i ++)
        {
            if (i + (1< a) continue;
            for (register int j = 1 ; j <= b ; j ++)
            {
                if (j + (1< b) continue;
                STn[i][j] = min(STn[i][j], min(STn[i + (1<1<1<1<<k)])));
                STx[i][j] = max(STx[i][j], max(STx[i + (1<1<1<1<<k)])));
            }
        }
    }
    for (register int i = 1 ; i <= a - n + 1 ; i ++)
    {
        for (register int j = 1 ; j <= b - n + 1 ; j ++)
        {
            ans = min(ans, Query(i, j));
        }
    }
    cout << ans;
    return 0;
}

 

转载于:https://www.cnblogs.com/BriMon/p/9281438.html

你可能感兴趣的:([HNOI2007] 理想正方形 二维ST表)