题目描述
给定一个(n imes m)的矩阵,对于每个$k imes k $的矩形,其权值为最大值减去最小值
求最小权值
(n,mleq 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
",ans);
return 0;
}
/*
f[i]表示i点往左n个数字的最小值
g[i]表示 最大值
ff[i][j]表示i,j为右下角的矩阵最小值
gg[i][j]表示 最大值
*/