没那么难,不需要什么二维单调队列,其实只要改变一下顺序就好
为了思路清晰,这里采用的结构体+结构体函数写的单调队列
刚开始感觉不会,看hzwer的blog,上面说,题解都太麻烦,还不如手推,就没继续看下去,事实证明这道题回来一看就秒了,也不知道是怎么想的。。。猜的?
其实就是一行一个单调队列,端点每往右移一位,就计算从上到下的情况
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;
int read()
{
int ans,f=1;char ch;
while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';
while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';
return ans*f;
}
struct aa
{
int q[1005],id[1005],head,tail;
aa ()
{
head=1;
tail=0;
}
void clear()
{
memset(q,0,sizeof(q));
memset(id,0,sizeof(id));
head=1;tail=0;
}
void mx_insert(int x,int idx)
{
while (q[tail]<=x && tail>=head) tail--;//pay attention,注意单调队列边界的情况即可
q[++tail]=x;id[tail]=idx;
}
void mi_insert(int x,int idx)
{
while (q[tail]>=x && tail>=head) tail--;
q[++tail]=x;id[tail]=idx;
}
void del(int k)
{
while (id[head]<=k&&head<=tail) head++;
}
}mx[1005],mi[1005],smi,smx;//单调队列
int a,b,n,mp[1005][1005],ans;
int main()
{
a=read();b=read();n=read();
for (int i=1;i<=a;i++)
for (int j=1;j<=b;j++) mp[i][j]=read();
ans=inf;
for (int i=1;i<=a;i++)
for (int j=1;j<=n;j++)
mx[i].mx_insert(mp[i][j],j),mi[i].mi_insert(mp[i][j],j);
for (int i=1;i<=b-n+1;i++)
{
smx.clear();
smi.clear();
for (int j=1;j<=n;j++)
smx.mx_insert(mx[j].q[mx[j].head],j),
smi.mi_insert(mi[j].q[mi[j].head],j);
for (int j=1;j<=a-n+1;j++)
{
ans=min(ans,smx.q[smx.head]-smi.q[smi.head]);
smx.del(j);
smi.del(j);
smx.mx_insert(mx[j+n].q[mx[j+n].head],j+n);
smi.mi_insert(mi[j+n].q[mi[j+n].head],j+n);
}
for (int j=1;j<=a;j++)
{
mx[j].del(i);
mi[j].del(i);
mx[j].mx_insert(mp[j][i+n],i+n);
mi[j].mi_insert(mp[j][i+n],i+n);
}
}
printf("%d",ans);
return 0;
}