HAOI2007 理想的正方形
|Word count:616|Reading time:3min|Post View:
题目链接
Luogu 2216
题目描述

题解
二维滑动窗口,先对每一行建立双端队列,记录每一个$1*n$的长方体中的极值,将二维矩阵压缩成$a$行$b-n+1$列的矩阵,再对每一列依次建立双端队列,记录$n*1$的长方体(在原矩阵中为$n*n$的正方形)中的极值($miny[i][t],maxy[i][t]$存储的是以$(i,t)$为右下角端点的$n*n$正方形的极值信息),枚举即可。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; const int inf = 0x7fffffff; const int N =1e3+1; inline int get(int &x) { x=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} } int x1[N],x2[N],headx1[N],tailx1[N],headx2[N],tailx2[N],minx[N][N],maxx[N][N]; int y1[N],y2[N],heady1[N],taily1[N],heady2[N],taily2[N],miny[N][N],maxy[N][N]; int mapp[N][N],a,b,n; long long ans=inf; int main() {
get(a),get(b),get(n); for(int i=1;i<=a;++i)for(int t=1;t<=b;++t)get(mapp[i][t]); for(int i=1;i<N;++i)headx1[i]=headx2[i]=heady1[i]=heady2[i]=1; for(int i=1;i<=a;++i) for(int t=1;t<=b;++t) { while(headx1[i]<=tailx1[i]&&mapp[i][x1[tailx1[i]]]>=mapp[i][t])tailx1[i]--; x1[++tailx1[i]]=t; while(headx1[i]<=tailx1[i]&&x1[headx1[i]]<=t-n)headx1[i]++; minx[i][t]=mapp[i][x1[headx1[i]]]; } for(int i=1;i<=a;++i) for(int t=1;t<=b;++t) { while(headx2[i]<=tailx2[i]&&mapp[i][x2[tailx2[i]]]<=mapp[i][t])tailx2[i]--; x2[++tailx2[i]]=t; while(headx2[i]<=tailx2[i]&&x2[headx2[i]]<=t-n)headx2[i]++; maxx[i][t]=mapp[i][x2[headx2[i]]]; } for(int t=n;t<=b;++t) for(int i=1;i<=a;++i) { while(heady1[t]<=taily1[t]&&minx[y1[taily1[t]]][t]>=minx[i][t])taily1[t]--; y1[++taily1[t]]=i; while(heady1[t]<=taily1[t]&&y1[heady1[t]]<=i-n)heady1[t]++; miny[i][t]=minx[y1[heady1[t]]][t]; } for(int t=n;t<=b;++t) for(int i=1;i<=a;++i) { while(heady2[t]<=taily2[t]&&maxx[y2[taily2[t]]][t]<=maxx[i][t])taily2[t]--; y2[++taily2[t]]=i; while(heady2[t]<=taily2[t]&&y2[heady2[t]]<=i-n)heady2[t]++; maxy[i][t]=maxx[y2[heady2[t]]][t]; } for(int t=n;t<=b;++t) for(int i=n;i<=a;++i) if(maxy[i][t]-miny[i][t]<ans)ans=maxy[i][t]-miny[i][t]; printf("%lld",ans); }
|