BZOJ 1047 理想的正方形

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<=10

 

Source

一个典型的单调队列dp,枚举矩阵左端,下端利用单调队列一路扫过,复杂度O(n2)。

我的代码不知道为什么神慢无比,险些TLE,仅供参考。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 #define inf (2000000000)
 7 #define maxn 1010
 8 int a,b,n,s[maxn][maxn],ans = inf;
 9 
10 inline int read()
11 {
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 struct node { int h,key; }q1[maxn*maxn],q2[maxn*maxn];
19 
20 inline void work()
21 {
22     int h1,t1,h2,t2;
23     int lef,rig,up,down;
24     for (lef = 1;lef+n-1 <= b;++lef)
25     {
26         rig = lef+n-1; up = 1; down = n;
27         h1 = t1 = h2 = t2 = 0;
28         for (int i = up;i <= down;++i)
29             for (int j = lef;j <= rig;++j)
30             {
31                 while (h1 < t1 && s[i][j] <= q1[t1].key) --t1;
32                 q1[++t1] = (node){i,s[i][j]};
33                 while (h2 < t2 && s[i][j] >= q2[t2].key) --t2;
34                 q2[++t2] = (node){i,s[i][j]};
35             }
36         ans = min(ans,q2[h2+1].key - q1[h1+1].key);
37         for (++down,++up;down <= a;++down,++up)
38         {
39             while (q1[h1+1].h < up) ++h1;
40             while (q2[h2+1].h < up) ++h2;
41             for (int i = lef;i <= rig;++i)
42             {
43                 while (h1 < t1 && s[down][i] <= q1[t1].key) --t1;
44                 q1[++t1] = (node){down,s[down][i]};
45                 while (h2 < t2 && s[down][i] >= q2[t2].key) --t2;
46                 q2[++t2] = (node){down,s[down][i]};
47             }
48             ans = min(ans,q2[h2+1].key - q1[h1+1].key);
49         }
50     }
51 }
52 
53 int main()
54 {
55     a = read(); b = read(); n = read();
56     for (int i = 1;i <= a;++i) for (int j = 1;j <= b;++j) s[i][j] = read();
57     work();
58     printf("%d",ans);
59     return 0;
60 }
View Code

 

posted @ 2015-02-16 14:25  lmxyy  阅读(208)  评论(0编辑  收藏  举报