P2216 [HAOI2007]理想的正方形

博客食用效果更佳

题目描述

给定一个\(n\times m\)的矩阵,对于每个$k\times k $的矩形,其权值为最大值减去最小值

求最小权值

\(n,m\leq 100\)

题解

滑动窗口的二维版

于是思路是优先队列优化dp

其实二维ST表也不是不行 但是卡在复杂度上界

想起当年静态二维RMQ写了2k树套树 一上午看到代码就想吐

我们可以一步步来,先对于每一行求出每个数前k个数字的最大最小值

然后以此类推求出每个矩形的最大最小值

虽然复杂度看起来是n方,但STL还是慢的离谱,不开O2甚至能T一个点

下次手写单调队列了/kk

#include<cstdio>
#include<queue>
using namespace std;
const int inf=0x7fffffff;
typedef long long ll;
#define maxn 1009
int n,m;
int k;
int a[maxn][maxn];
int f[maxn][maxn],g[maxn][maxn],ff[maxn][maxn],gg[maxn][maxn]; 
signed 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 j=1;j<=n;j++)
	{
		priority_queue<pair<int,int> > q2; 
		priority_queue<pair<int,int> ,vector<pair<int,int> > ,greater<pair<int,int> > > q;
		for(int i=1;i<=m;i++)
		{
			while(!q.empty()&&i-q.top().second>=k)q.pop();
			while(!q2.empty()&&i-q2.top().second>=k)q2.pop(); 
			q.push(make_pair(a[j][i],i));
			q2.push(make_pair(a[j][i],i));
			f[j][i]=q.top().first;
			g[j][i]=q2.top().first;
		}
	}
	for(int i=1;i<=m;i++)
	{
		priority_queue<pair<int,int> > q2;
		priority_queue<pair<int,int> ,vector<pair<int,int> > ,greater<pair<int,int> > > q;
		for(int j=1;j<=n;j++)
		{
			while(!q.empty()&&j-q.top().second>=k)q.pop();
			while(!q2.empty()&&j-q2.top().second>=k)q2.pop(); 
			q.push((make_pair(f[j][i],j)));
			q2.push((make_pair(g[j][i],j)));
			ff[j][i]=q.top().first;
			gg[j][i]=q2.top().first;
		}
	}
	int ans=inf;
	for(int i=k;i<=n;i++)
	{
		for(int j=k;j<=m;j++)
		{
			ans=min(gg[i][j]-ff[i][j],ans);
			//cout<<i<<" "<<j<<" max:"<<gg[i][j]<<" min:"<<ff[i][j] <<endl;
		}
	}
	printf("%d\n",ans);
	return 0;
}
/*
f[i]表示i点往左n个数字的最小值 
g[i]表示                最大值 
ff[i][j]表示i,j为右下角的矩阵最小值 
gg[i][j]表示          最大值 
*/
posted @ 2021-08-18 19:26  lzylzy/kk  阅读(39)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end