【看了题解才会做
这是一个典型的二维滑动窗口问题~
二维滑动窗口问题的处理方法可以类比一维滑动窗口的处理方法
首先将矩阵分解成B个列,对这B个列分别用单调队列维护一个长度为N的一维滑动窗口。记录colmax[i][j]为第j列第i行的元素(即第j个列的第i个元素)到第j列第i-N+1的元素(即第j个列的第i-N+1个元素)的最大值。这个用单调队列随便维护一下就好啦~
然后将矩阵分解成A个行,对这A个行再分别用单调队列维护一个长度为N的一维滑动窗口。记录rowmax[i][j]为colmax[i][j]~colmax[i][j-N+1]的最大值。显然地,此时rowmax[i][j]就是第i行第j列的元素到第i-N+1行第j-N+1列的元素(二维的)的最大值。
然后再做一遍最小值的。最后扫描一遍就可以啦~
1 #include <deque> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 void Get_Val(int &Ret) 9 { 10 Ret = 0; 11 char ch; 12 while ((ch = getchar()), (ch > ‘9‘ || ch < ‘0‘)) 13 ; 14 do 15 { 16 (Ret *= 10) += ch - ‘0‘; 17 } 18 while ((ch = getchar()), (ch >= ‘0‘ && ch <= ‘9‘)); 19 } 20 21 const size_t Max_AB(1050); 22 23 int A, B; 24 int N; 25 int Value[Max_AB][Max_AB]; 26 27 int colmax[Max_AB][Max_AB], rowmax[Max_AB][Max_AB]; 28 int colmin[Max_AB][Max_AB], rowmin[Max_AB][Max_AB]; 29 30 void init() 31 { 32 Get_Val(A), Get_Val(B), Get_Val(N); 33 for (int i = 1;i <= A;++i) 34 for (int j = 1;j <= B;++j) 35 Get_Val(Value[i][j]); 36 } 37 38 struct node 39 { 40 node(const int &a = 0, const int &b = 0) : Number(a), Value(b) {} 41 int Number; 42 int Value; 43 }; 44 45 void Col_Max(int col[][Max_AB]) 46 { 47 deque<node> Q; 48 for (int j = 1;j <= B;++j) 49 { 50 Q.clear(); 51 for (int i = 1;i <= A;++i) 52 { 53 while (!Q.empty() && Q.back().Value < Value[i][j]) 54 Q.pop_back(); 55 Q.push_back(node(i, Value[i][j])); 56 if (Q.front().Number < i - N + 1) 57 Q.pop_front(); 58 col[i][j] = Q.front().Value; 59 } 60 } 61 } 62 63 void Row_Max(int col[][Max_AB], int row[][Max_AB]) 64 { 65 deque<node> Q; 66 for (int i = 1;i <= A;++i) 67 { 68 Q.clear(); 69 for (int j = 1;j <= B;++j) 70 { 71 while (!Q.empty() && Q.back().Value < col[i][j]) 72 Q.pop_back(); 73 Q.push_back(node(j, col[i][j])); 74 if (Q.front().Number < j - N + 1) 75 Q.pop_front(); 76 row[i][j] = Q.front().Value; 77 } 78 } 79 } 80 81 void work() 82 { 83 Col_Max(colmax); 84 Row_Max(colmax, rowmax); 85 for (int i = 1;i <= A;++i) 86 for (int j = 1;j <= B;++j) 87 Value[i][j] = -Value[i][j]; 88 Col_Max(colmin); 89 Row_Max(colmin, rowmin); 90 } 91 92 void Get_Ans() 93 { 94 int Ans(0X7F7F7F7F); 95 for (int i = N;i <= A;++i) 96 for (int j = N;j <= B;++j) 97 Ans = min(Ans, rowmax[i][j] + rowmin[i][j]); 98 printf("%d", Ans); 99 } 100 101 int main() 102 { 103 init(); 104 work(); 105 Get_Ans(); 106 return 0; 107 }
BZOJ 1047
时间: 2024-10-25 19:25:54