[luoguP2216] [HAOI2007]理想的正方形(二维单调队列)

传送门

1.先弄个单调队列求出每一行的区间为n的最大值最小值。

2.然后再搞个单调队列求1所求出的结果的区间为n的最大值最小值

3.最后扫一遍就行

懒得画图,自己体会吧。

——代码

 1 #include <cstdio>
 2 #include <iostream>
 3 
 4 using namespace std;
 5 
 6 const int MAXN = 1001;
 7 int a, b, n, h, t;
 8 long long c[MAXN][MAXN], q[MAXN], max1[MAXN][MAXN], min1[MAXN][MAXN], max2[MAXN][MAXN], min2[MAXN][MAXN], ans = 1000000001;
 9 
10 inline void work1(int k)
11 {
12     int i, j;
13     h = 1, t = 0;
14     for(i = 1; i <= b; i++)
15     {
16         while(h <= t && c[k][q[t]] > c[k][i]) t--;
17         q[++t] = i;
18         while(h <= t && q[h] <= i - n) h++; 
19         min1[k][i] = c[k][q[h]];
20     }
21     h = 1; t = 0;
22     for(i = 1; i <= b; i++)
23     {
24         while(h <= t && c[k][q[t]] < c[k][i]) t--;
25         q[++t] = i;
26         while(h <= t && q[h] <= i - n) h++; 
27         max1[k][i] = c[k][q[h]];
28     }
29 }
30 
31 inline void work2(int k)
32 {
33     int i, j;
34     h = 1, t = 0;
35     for(i = 1; i <= a; i++)
36     {
37         while(h <= t && min1[q[t]][k] > min1[i][k]) t--;
38         q[++t] = i;
39         while(h <= t && q[h] <= i - n) h++; 
40         min2[i][k] = min1[q[h]][k];
41     }
42     h = 1; t = 0;
43     for(i = 1; i <= a; i++)
44     {
45         while(h <= t && max1[q[t]][k] < max1[i][k]) t--;
46         q[++t] = i;
47         while(h <= t && q[h] <= i - n) h++; 
48         max2[i][k] = max1[q[h]][k];
49     }
50 }
51 
52 int main()
53 {
54     int i, j;
55     scanf("%d %d %d", &a, &b, &n);
56     for(i = 1; i <= a; i++)
57         for(j = 1; j <= b; j++)
58             scanf("%lld", &c[i][j]);
59     for(i = 1; i <= a; i++) work1(i);
60     for(i = 1; i <= b; i++) work2(i);
61     for(i = n; i <= a; i++)
62         for(j = n; j <= b; j++)
63             ans = min(ans, max2[i][j] - min2[i][j]);
64     printf("%lld", ans);
65     return 0;
66 }
View Code
原文地址:https://www.cnblogs.com/zhenghaotian/p/6819813.html