理想的正方形(单调队列在二维的应用)
题解:
用单调队列分别维护行与列。
这里只讲求 n*n 区间内的最大值的维护方法,最小值同样的方法维护即可。
具体实现方法:
- 遍历每一行,从上到下维护每一列的每一段n长度内的最大值,得到y_max数组;
- 之后遍历y_max数组,也是遍历每一行,不过这时候要从左到右维护了,也就是行内维护,维护每一行内长度为n的区间内的最大值,得到x_max数组;
- x_max数组就是原数组从左到右,从上到下每一个n*n区间内的最大值了。
代码说明:
原数组:mat,列数组:Q;
遍历每一行,当行达到了n,就说明列向已经满足了n,这个时候就开始在行内维护n长度的最大值了(也就是说我的代码并没有完全等到y_max构造完就开始构造x_max了)
AC_Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int inf = 0x3f3f3f3f; 5 6 struct Container{ 7 deque<int> qmin; 8 deque<int> qmax; 9 Container():qmin(), qmax() {} 10 void push(int n){ 11 while( !qmin.empty() && qmin.back()>n ) qmin.pop_back(); 12 qmin.push_back(n); 13 while( !qmax.empty() && qmax.back()<n ) qmax.pop_back(); 14 qmax.push_back(n); 15 } 16 void pop(int n){ 17 if( qmin.size() && qmin.front()==n ) qmin.pop_front(); 18 if( qmax.size() && qmax.front()==n ) qmax.pop_front(); 19 } 20 int _max(){ 21 return qmax.front(); 22 } 23 int _min(){ 24 return qmin.front(); 25 } 26 }; 27 28 int main() 29 { 30 int a,b,n; 31 scanf("%d%d%d",&a,&b,&n); 32 vector<vector<int> > mat(a,vector<int>(b)); 33 for(auto &v: mat){ 34 for(auto &i: v){ 35 scanf("%d",&i); 36 } 37 } 38 vector<Container>Q(b);//列 39 int ans = inf; 40 for(int i=0; i<a; i++){ 41 if( i>=n ){ //纵向维护 42 for(int j=0;j<b;j++){ 43 Q[j].pop(mat[i-n][j]);//因为是单调维护,所以把mat[i-n][j]相同的值删掉就相当于把他及之前的数都给删掉了 44 } 45 } 46 for(int j=0;j<b;j++){ //纵向维护 47 Q[j].push(mat[i][j]); 48 } 49 if( i<n-1 ) continue; //因为要是n*n的,所以首先要满足纵向长度达到了n 50 Container C; 51 for(int j=0;j<b;j++){ //横向维护 52 if( j-n>=0 ){ 53 C.pop(Q[j-n]._max()); 54 C.pop(Q[j-n]._min()); 55 } 56 C.push(Q[j]._max()); 57 C.push(Q[j]._min()); 58 if( j>=n-1 ) ans = min(ans,C._max()-C._min()); 59 } 60 } 61 printf("%d\n",ans); 62 return 0; 63 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int inf = 0x3f3f3f3f; 5 6 struct node{ 7 int val; 8 int idx; 9 }; 10 deque<node>col_qmin[maxn], col_qmax[maxn], row_qmin, row_qmax; 11 int mat[maxn][maxn]; 12 13 int main() 14 { 15 int a,b,n; 16 scanf("%d%d%d",&a,&b,&n); 17 for(int i=0;i<a;i++) for(int j=0;j<b;j++) scanf("%d",&mat[i][j]); 18 int ans = inf; 19 for(int i=0; i<a; i++){ 20 if( i>=n ){ 21 for(int j=0;j<b;j++){ 22 while( col_qmin[j].size() && col_qmin[j].front().idx<=i-n ) col_qmin[j].pop_front(); 23 while( col_qmax[j].size() && col_qmax[j].front().idx<=i-n ) col_qmax[j].pop_front(); 24 } 25 } 26 for(int j=0;j<b;j++){ 27 while( col_qmin[j].size() && col_qmin[j].back().val>mat[i][j] ) col_qmin[j].pop_back(); 28 col_qmin[j].push_back(node{mat[i][j],i}); 29 while( col_qmax[j].size() && col_qmax[j].back().val<mat[i][j] ) col_qmax[j].pop_back(); 30 col_qmax[j].push_back(node{mat[i][j],i}); 31 } 32 33 if( i<n-1 ) continue; 34 row_qmin.clear(); row_qmax.clear(); 35 36 for(int j=0;j<b;j++){ 37 if( j>=n ){ 38 while( row_qmin.size() && row_qmin.front().idx<=j-n ) row_qmin.pop_front(); 39 while( row_qmax.size() && row_qmax.front().idx<=j-n ) row_qmax.pop_front(); 40 } 41 while( row_qmin.size() && row_qmin.back().val>col_qmin[j].front().val ) row_qmin.pop_back(); 42 row_qmin.push_back(node{col_qmin[j].front().val,j}); 43 while( row_qmax.size() && row_qmax.back().val<col_qmax[j].front().val ) row_qmax.pop_back(); 44 row_qmax.push_back(node{col_qmax[j].front().val,j}); 45 46 if( j>=n-1 ){ 47 ans = min(ans,row_qmax.front().val-row_qmin.front().val); 48 } 49 } 50 } 51 printf("%d\n",ans); 52 return 0; 53 }