#1108 理想的正方形
描述
有一个ab的整数组成的矩阵,现请你从中找出一个nn的正方形区域,使得该区域所有数中的最大值和最小值 的差最小。
输入
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每 行相邻两数之间用一空格分隔。 100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
输出
仅一个整数,为ab矩阵中所有“nn正方形区域中的最大整数和最小整数的差值”的最小值。
样例输入 [复制]
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
样例输出 [复制]
1
问题规模
(1)矩阵中的所有数都不超过1,000,000,000 (2)20%的数据2<=a,b<=100,n<=a,n<=b,n<=10 (3)100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
简单的 单调队列 注意二维处理 不完全是 “正方形的平移”
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int a[maxn][maxn];
int head[maxn][2],tail[maxn][2];
struct atom{
int id,s;
}q[maxn][maxn][2],now[maxn][2];
int t[2];
int l[2],r[2];
signed main(){
int n,m,N;
scanf("%d%d%d",&n,&m,&N);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&a[i][j]);
}
}
memset(tail,-1,sizeof tail);
memset(head,0,sizeof head);
int ans=2e9;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
while(head[j][0]<=tail[j][0]&&q[j][head[j][0]][0].id<=i-N)++head[j][0];
while(head[j][0]<=tail[j][0]&&q[j][tail[j][0]][0].s<=a[i][j])--tail[j][0];
q[j][++tail[j][0]][0]=(atom){i,a[i][j]};
while(head[j][1]<=tail[j][1]&&q[j][head[j][1]][1].id<=i-N)++head[j][1];
while(head[j][1]<=tail[j][1]&&q[j][tail[j][1]][1].s>=a[i][j])--tail[j][1];
q[j][++tail[j][1]][1]=(atom){i,a[i][j]};
}
if(i>=N){
l[0]=l[1]=0,r[0]=r[1]=-1;
for(int j=1;j<=m;++j){
t[0]=q[j][head[j][0]][0].s,t[1]=q[j][head[j][1]][1].s;
while(l[0]<=r[0]&&now[l[0]][0].id<=j-N)++l[0];
while(l[0]<=r[0]&&now[r[0]][0].s<=t[0])--r[0];
now[++r[0]][0]=(atom){j,t[0]};
while(l[1]<=r[1]&&now[l[1]][1].id<=j-N)++l[1];
while(l[1]<=r[1]&&now[r[1]][1].s>=t[1])--r[1];
now[++r[1]][1]=(atom){j,t[1]};
if(j>=N)ans=min(ans,now[l[0]][0].s-now[l[1]][1].s);
}
}
}
printf("%d",ans);
return 0;
}