1. 程式人生 > >[luoguP2216] [HAOI2007]理想的正方形(二維單調隊列)

[luoguP2216] [HAOI2007]理想的正方形(二維單調隊列)

++ pla https hide 正方形 closed log 傳送門 name

傳送門

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

[luoguP2216] [HAOI2007]理想的正方形(二維單調隊列)