【单调】理想的正方形
程序员文章站
2022-06-05 13:47:15
...
luoguP2216
【HAOI2007】
题目:有一个ab的整数组成的矩阵,现请你从中找出一个nn的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
题解:二维滑动窗口
一维是维护i结尾的最值,二维就是维护一维维护后的最值。
垃圾图解:
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10,K=1e2;
int n,m,k;
int a[N][N],ma[N][N],mi[N][N];
int z[N],c[N];
int p1,p2,q1,q2;
int f1[N][N],f2[N][N];
int g1[N][N],g2[N][N];
void clean()
{
memset(z,0,sizeof(z));
memset(c,0,sizeof(c));
p1=1;p2=0;q1=1;q2=0;
}
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++)
{
clean();
for(int j=1;j<=m;j++)
{
while(p1<=p2&&j-z[p1]>=k)p1++;
while(q1<=q2&&j-c[q1]>=k)q1++;
while(p1<=p2&&a[i][z[p2]]>a[i][j])p2--;//<
while(q1<=q2&&a[i][c[q2]]<a[i][j])q2--;//>
z[++p2]=j;c[++q2]=j;
f1[i][j]=a[i][z[p1]];
f2[i][j]=a[i][c[q1]];
//for(int k=p1;k<=p2;k++)printf("(%2d,%2d)",i,z[k]);
}
}
for(int j=1;j<=m;j++)
{
clean();
for(int i=1;i<=n;i++)
{
while(p1<=p2&&i-z[p1]>=k)p1++;
while(q1<=q2&&i-c[q1]>=k)q1++;
while(p1<=p2&&f1[z[p2]][j]>f1[i][j])p2--;//<
while(q1<=q2&&f2[c[q2]][j]<f2[i][j])q2--;//>
z[++p2]=i;c[++q2]=i;
g1[i][j]=f1[z[p1]][j];
g2[i][j]=f2[c[q1]][j];
}
}
int ans=1e9;
for(int i=k;i<=n;i++)
for(int j=k;j<=m;j++)
ans=min(ans,g2[i][j]-g1[i][j]);
printf("%d",ans);
}