P2216 [HAOI2007]理想的正方形
在二维上运用单调队列,我们可以想象在矩阵上移动滑动窗口,以左上角为起点,在在窗口内部我们对每一行求最值,再对每一列求最值,那么左上角的元素一定是最值,只需要将每个滑动窗口最值存储即可
没什么坑,有思路很快就能做出来
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1010; 4 int c[N][N],tmpx[N][N],tmpX[N][N],q[N],Q[N];//求每一行n范围的最大值、最小值再对其求每一列的最值 5 int main()//以左上角坐标为基准 6 { 7 // freopen("in.txt","r",stdin); 8 int a,b,n,ans = INT_MAX; 9 scanf("%d%d%d",&a,&b,&n); 10 for(int i=1;i<=a;i++) 11 for(int j=1;j<=b;j++) 12 scanf("%d",&c[i][j]); 13 for(int i=1;i<=a;i++){ 14 int tt = -1,TT = -1,hh = 0,HH = 0; 15 for(int j=1;j<=b;j++){ 16 while(hh<=tt&&q[hh]<j-n+1) ++hh; 17 while(HH<=TT&&Q[HH]<j-n+1) ++HH; 18 while(hh<=tt&&c[i][q[tt]]>=c[i][j]) --tt; 19 while(HH<=TT&&c[i][Q[TT]]<=c[i][j]) --TT; 20 q[++tt] = j; Q[++TT] = j; 21 if(j-n+1>0){ 22 tmpx[i][j-n+1] = c[i][q[hh]]; 23 tmpX[i][j-n+1] = c[i][Q[HH]];//对应每一个滑动窗口行的最值 24 } 25 } 26 } 27 for(int j=1;j<=b-n+1;j++){ 28 int tt = -1,TT = -1,hh = 0,HH = 0; 29 for(int i=1;i<=a;i++){ 30 while(hh<=tt&&q[hh]<i-n+1) ++hh; 31 while(HH<=TT&&Q[HH]<i-n+1) ++HH; 32 while(hh<=tt&&tmpx[q[tt]][j]>=tmpx[i][j]) --tt; 33 while(HH<=TT&&tmpX[Q[TT]][j]<=tmpX[i][j]) --TT; 34 q[++tt] = i; Q[++TT] = i; 35 if(i-n+1>0){ 36 tmpx[i-n+1][j] = tmpx[q[hh]][j]; 37 tmpX[i-n+1][j] = tmpX[Q[HH]][j];//对应每一个滑动窗口行的最值 38 } 39 } 40 } 41 for(int i=1;i<=a-n+1;i++) 42 for(int j=1;j<=b-n+1;j++) 43 ans = min(ans,tmpX[i][j]-tmpx[i][j]); 44 printf("%d\n",ans); 45 return 0; 46 }