P2216 [HAOI2007]理想的正方形方法记录( 二 )


然后只需要遍历一遍 , 求出最小的\(y2[i][j]-y1[i][j]\)即可 。
#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>using namespace std;const int N=1005;int a,b,n;int board[N][N];int x1[N][N],x2[N][N],y1[N][N],y2[N][N];int q1[N],q2[N];int cntx1,cntx2,cnty1,cnty2;int minn(int a,int b){ return a<b?a:b;}int ans=2147483647;int main(){ scanf("%d%d%d",&a,&b,&n); for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)scanf("%d",&board[i][j]); for(int i=1;i<=a;i++) {int h=0,t=0;memset(q1,0,sizeof(q1));memset(q2,0,sizeof(q2));for(int j=1;j<=b;j++){while(h<=t&&j-q1[h]>=n) h++;while(h<=t&&board[i][j]<board[i][q1[t]]) t--;q1[++t]=j;if(j>=n) x1[i][j-n+1]=board[i][q1[h]];}for(int j=1;j<=b;j++){while(h<=t&&j-q2[h]>=n) h++;while(h<=t&&board[i][j]>board[i][q2[t]]) t--;q2[++t]=j;if(j>=n) x2[i][j-n+1]=board[i][q2[h]];} } memset(q1,0,sizeof(q1)); memset(q2,0,sizeof(q2)); for(int i=1;i<=b-n+1;i++) {int h=0,t=0;memset(q1,0,sizeof(q1));memset(q2,0,sizeof(q2));for(int j=1;j<=a;j++){while(h<=t&&j-q1[h]>=n) h++;while(h<=t&&x1[j][i]<x1[q1[t]][i]) t--;q1[++t]=j;if(j>=n) y1[j-n+1][i]=x1[q1[h]][i];}for(int j=1;j<=a;j++){while(h<=t&&j-q2[h]>=n) h++;while(h<=t&&x2[j][i]>x2[q2[t]][i]) t--;q2[++t]=j;if(j>=n) y2[j-n+1][i]=x2[q2[h]][i];} } for(int i=1;i<=a-n+1;i++)for(int j=1;j<=b-n+1;j++)ans=minn(ans,y2[i][j]-y1[i][j]); printf("%d\n",ans); return 0;}

经验总结扩展阅读