题意:求矩形中差异值最大不超过c的子矩阵的最大面积。
题解:枚举子矩形左右两列,然后记录每行位于这两列之间的最大最小值,建两个单调队列,从上往下一次扫描时,判断差异值是否超过了c,以此来维护队列,再加最优化剪枝。
View Code
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=705; int row,col,c; int map[N][N],_min[N],_max[N];//min/max:第i行[a,b]区间最大/小值 int Q1[N*2],Q2[N*2],f1,f2,r1,r2; void push1(int k) { while(f1<=r1&&_min[Q1[r1]]>_min[k]) r1--; Q1[++r1]=k; } void push2(int k) { while(f2<=r2&&_max[Q2[r2]]<_max[k]) r2--; Q2[++r2]=k; } int main() { while(scanf("%d%d%d",&col,&row,&c)!=EOF) { for(int i=0;i<row;i++) for(int j=0;j<col;j++) scanf("%d",&map[i][j]); int ans=0; for(int i=0;i<col;i++) { for(int j=0;j<row;j++) _min[j]=_max[j]=map[j][i]; for(int j=i+1;j<col&&j-i<100;j++) { for(int k=0;k<row;k++) { _min[k]=min(_min[k],map[k][j]); _max[k]=max(_max[k],map[k][j]); } f1=f2=0; r1=r2=-1; int w=j-i+1; for(int r=0,f=0;r<row&&(row-f)*w>ans;r++) { push1(r); push2(r); while(f<=r&&f1<=r1&&f2<=r2&&_max[Q2[f2]]-_min[Q1[f1]]>c) { f++; while(f2<=r2&&Q2[f2]<f) f2++; while(f1<=r1&&Q1[f1]<f) f1++; } ans=max(ans,w*(r-f+1)); } } } printf("%d\n",ans); } return 0; }