[HAOI 2007]理想的正方形

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

题解

网上的题解有用单调队列做的,私认为这道题暴力完全可以水过去...

这里给出一种$RMQ$的做法。

二维的$RMQ$求正方形内的最值,和一维没什么不同,只是倍增以及询问的时候要分四块。

 1 #include<cmath>
 2 #include<ctime>
 3 #include<stack>
 4 #include<queue>
 5 #include<string>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<cstdlib>
 9 #include<iostream>
10 #include<algorithm>
11  using namespace std;
12 const int N=1000;
13 
14 int a,b,n,op;
15 int minn[N+5][N+5][15],maxn[N+5][N+5][15];
16 
17 int main()
18 {
19     scanf("%d%d%d",&a,&b,&n);
20     for (int i=1;i<=a;i++)
21         for (int j=1;j<=b;j++)
22         {
23             scanf("%d",&minn[i][j][0]);
24             maxn[i][j][0]=minn[i][j][0];
25         }
26     op=log2(n);
27     for (int t=1;t<=op;t++)
28         for (int i=1;i+(1<<t)-1<=a;i++)
29             for (int j=1;j+(1<<t)-1<=b;j++)
30             {
31                 minn[i][j][t]=min(minn[i][j][t-1],minn[i][j+(1<<t-1)][t-1]);
32                 minn[i][j][t]=min(minn[i][j][t],minn[i+(1<<t-1)][j][t-1]);
33                 minn[i][j][t]=min(minn[i][j][t],minn[i+(1<<t-1)][j+(1<<t-1)][t-1]);
34                 maxn[i][j][t]=max(maxn[i][j][t-1],maxn[i][j+(1<<t-1)][t-1]);
35                 maxn[i][j][t]=max(maxn[i][j][t],maxn[i+(1<<t-1)][j][t-1]);
36                 maxn[i][j][t]=max(maxn[i][j][t],maxn[i+(1<<t-1)][j+(1<<t-1)][t-1]);
37             }
38     int ansmax,ansmin,ans=2e9;
39     for (int i=1;i+n-1<=a;i++)
40         for (int j=1;j+n-1<=b;j++)
41         {
42             ansmax=max(maxn[i][j][op],maxn[i][j+n-(1<<op)][op]);
43             ansmax=max(ansmax,maxn[i+n-(1<<op)][j][op]);
44             ansmax=max(ansmax,maxn[i+n-(1<<op)][j+n-(1<<op)][op]);
45             ansmin=min(minn[i][j][op],minn[i][j+n-(1<<op)][op]);
46             ansmin=min(ansmin,minn[i+n-(1<<op)][j][op]);
47             ansmin=min(ansmin,minn[i+n-(1<<op)][j+n-(1<<op)][op]);
48             ans=min(ans,ansmax-ansmin);
49         }
50     printf("%d
",ans);
51     return 0;
52 }
原文地址:https://www.cnblogs.com/NaVi-Awson/p/7262761.html