【单调队列】bzoj1047 [HAOI2007]理想的正方形
先把整个矩阵处理成b[n][m-K+1]、c[n][m-K+1]大小的两个矩阵,分别存储每行每K个数中的最大、最小值,然后再通过b、c处理出d、e分别表示K*K大小的子矩阵中的最大、最小值即可。单调队列暴力。
#include<cstdio> #include<algorithm> using namespace std; #define N 1001 int n,m,K,a[N][N],b[N][N],c[N][N],q[N],head,tail,d[N][N],e[N][N]; int ans=2147483647; int main() { scanf("%d%d%d",&n,&m,&K); for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",&a[i][j]); for(int i=1;i<=n;++i) { head=tail=q[1]=1; for(int j=2;j<=K;++j) { while(a[i][j]<=a[i][q[tail]] && tail>=head) --tail; q[++tail]=j; } b[i][1]=a[i][q[head]]; for(int j=K+1;j<=m;++j) { if(q[head]<j-K+1) ++head; while(a[i][j]<=a[i][q[tail]] && tail>=head) --tail; q[++tail]=j; b[i][j-K+1]=a[i][q[head]]; } head=tail=q[1]=1; for(int j=2;j<=K;++j) { while(a[i][j]>=a[i][q[tail]] && tail>=head) --tail; q[++tail]=j; } c[i][1]=a[i][q[head]]; for(int j=K+1;j<=m;++j) { if(q[head]<j-K+1) ++head; while(a[i][j]>=a[i][q[tail]] && tail>=head) --tail; q[++tail]=j; c[i][j-K+1]=a[i][q[head]]; } } for(int i=1;i<=m-K+1;++i) { head=tail=q[1]=1; for(int j=2;j<=K;++j) { while(b[j][i]<=b[q[tail]][i] && tail>=head) --tail; q[++tail]=j; } d[1][i]=b[q[head]][i]; for(int j=K+1;j<=n;++j) { if(q[head]<j-K+1) ++head; while(b[j][i]<=b[q[tail]][i] && tail>=head) --tail; q[++tail]=j; d[j-K+1][i]=b[q[head]][i]; } head=tail=q[1]=1; for(int j=2;j<=K;++j) { while(c[j][i]>=c[q[tail]][i] && tail>=head) --tail; q[++tail]=j; } e[1][i]=c[q[head]][i]; for(int j=K+1;j<=n;++j) { if(q[head]<j-K+1) ++head; while(c[j][i]>=c[q[tail]][i] && tail>=head) --tail; q[++tail]=j; e[j-K+1][i]=c[q[head]][i]; } } for(int i=1;i<=n-K+1;++i) for(int j=1;j<=m-K+1;++j) ans=min(ans,e[i][j]-d[i][j]); printf("%d\n",ans); return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/