[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 <iostream> #include <cstdio> #include <cmath> 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<<tt) + n][y], max(STx[x][y - (1<<tt) + n], STx[x - (1<<tt) + n][y - (1<<tt) + n]))) ; minn = min(STn[x][y], min(STn[x - (1<<tt) + n][y], min(STn[x][y - (1<<tt) + n], STn[x - (1<<tt) + n][y - (1<<tt) + 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<<k) > a) continue; for (register int j = 1 ; j <= b ; j ++) { if (j + (1<<k) > b) continue; STn[i][j] = min(STn[i][j], min(STn[i + (1<<k)][j + (1<<k)], min(STn[i + (1<<k)][j], STn[i][j + (1<<k)]))); STx[i][j] = max(STx[i][j], max(STx[i + (1<<k)][j + (1<<k)], max(STx[i + (1<<k)][j], STx[i][j + (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; }