1047: [HAOI2007]理想的正方形

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 4075  Solved: 2277
[Submit][Status][Discuss]

Description

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

Input

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

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
 
二维单调队列
先计算每行前n个点的最大值和最小值,用单调队列维护。
然后按列的顺序计算每个点作为右下角时,矩阵的最大值和最小值。
简单来说,就是多次运用单调队列,将二维矩阵压缩为一维矩阵求解
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 const int MAXN=1000+5;
 6 const int INF=0x7fffffff;
 7 
 8 int a,b,n,ans=INF;
 9 int s[MAXN][MAXN],mx[MAXN][MAXN],mn[MAXN][MAXN];
10 int val[MAXN],pos[MAXN],x[MAXN],y[MAXN];
11 
12 int main()
13 {
14     scanf("%d %d %d",&a,&b,&n);
15     for(int i=1;i<=a;i++)
16         for(int j=1;j<=b;j++)
17             scanf("%d",&s[i][j]);
18     int l,r;
19     for(int i=1;i<=a;i++)
20     {
21         l=1,r=1;
22         for(int j=1;j<=b;j++)
23         {
24             while(l<r&&val[r-1]<=s[i][j]) r--;
25             val[r]=s[i][j];pos[r]=j;r++;
26             if(pos[l]==j-n) l++;
27             if(j>=n) mx[i][j]=val[l];
28         }
29         l=1,r=1;
30         for(int j=1;j<=b;j++)
31         {
32             while(l<r&&val[r-1]>=s[i][j]) r--;
33             val[r]=s[i][j];pos[r]=j;r++;
34             if(pos[l]==j-n) l++;
35             if(j>=n) mn[i][j]=val[l];
36         }
37     }
38     for(int i=n;i<=b;i++)
39     {
40         l=1,r=1;
41         for(int j=1;j<=a;j++)
42         {
43             while(l<r&&val[r-1]<=mx[j][i]) r--;
44             val[r]=mx[j][i];pos[r]=j;r++;
45             if(pos[l]==j-n) l++;
46             if(j>=n) x[j]=val[l];
47         }
48         l=1,r=1;
49         for(int j=1;j<=a;j++)
50         {
51             while(l<r&&val[r-1]>=mn[j][i]) r--;
52             val[r]=mn[j][i];pos[r]=j;r++;
53             if(pos[l]==j-n) l++;
54             if(j>=n) y[j]=val[l];
55         }
56         for(int i=n;i<=a;i++) ans=min(ans,x[i]-y[i]);
57     }
58     printf("%d
",ans);
59     return 0;
60 }
原文地址:https://www.cnblogs.com/InWILL/p/9337841.html