【单调】理想的正方形

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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值