[TK] 理想的正方形

题目描述

有一个整数组成的矩阵,现请你从中找出一个指定边长的正方形区域,使得该区域所有数中的最大值和最小值的差最小。

题目分析

其实这道题和滑动窗口很像,而滑动窗口使用优先队列解决.
我们都知道优先队列可以维护区间最值. 但是优先队列维护的区间不是二维的,而是一维的.
因此,这道题我们的思考方向,一是把优先队列拓展到二维,二是用一维优先队列解决问题.

思考一下怎么用一维优先队列解决问题,我们可以发现,一个区间内的最大值等于各行最大值的最大值,最小值等于各行最小值的最小值. 这启发我们采用先一维再一维的方式解决问题.

因此,我们需要做的是,跑出每行滑动窗口的最值,再跑出相同列滑动窗口最值的最值,在所有最值中选择最优解

代码实现

注: 使用了 封装滑动窗口

MMMW m[1001];
MMMW om[2][1001];
int a,b,n,ans=0x7fffffff;
int main(){
	cin>>a>>b>>n;
	for(int i=1;i<=a;++i){
		for(int j=1;j<=b;++j){
			cin>>m[i].a[j];
		}
		for(int j=1;j<=n-1;++j){
			m[i].push(j);
		}
		for(int j=n;j<=b;++j){
			m[i].out(j-n);
			m[i].push(j);
			om[0][j].a[i]=m[i].max();
			om[1][j].a[i]=m[i].min();
		}
	}
	for(int i=n;i<=b;++i){
		for(int j=1;j<=n-1;++j){
			om[0][i].push(j);
			om[1][i].push(j);
		}
		for(int j=n;j<=a;++j){
			om[0][i].out(j-n);
			om[0][i].push(j);
			om[1][i].out(j-n);
			om[1][i].push(j);
			ans=min(ans,om[0][i].max()-om[1][i].min());
		}
	}
	cout<<ans;
}
posted @ 2024-02-22 08:20  HaneDaniko  阅读(8)  评论(0编辑  收藏  举报