萌新冒泡
记得很早之前A过 不过忘完了 当年毫无思路只会暴力 现在能够独立打出来AC啦 虽然还是很菜 不过看到进步就挺开心的
思路就是找出每一个点往上延伸k个的最大值,最小值 然后再把每段长度为k的再看做一个整体
注意细节就好
#include<bits/stdc++.h>
#define N 1005
const int INF=0x3f3f3f3f;
using namespace std;
int n,m,k,v[N][N],d1[N][N],d2[N][N],q[N];
int maxx[N][N],minx[N][N];
int main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>v[i][j];
for(int i=1;i<=m;i++) //枚举列
{
memset(q,0,sizeof(q)); int head=1,tail=0;
for(int j=1;j<=n;j++)
{
while(head<=tail&&j-q[head]>=k) head++;
while(head<=tail&&v[j][i]>=v[q[tail]][i]) tail--;
q[++tail]=j;
d1[j][i]=v[q[head]][i];
}
memset(q,0,sizeof(q)); head=1,tail=0;
for(int j=1;j<=n;j++)
{
while(head<=tail&&j-q[head]>=k) head++;
while(head<=tail&&v[j][i]<=v[q[tail]][i]) tail--;
q[++tail]=j;
d2[j][i]=v[q[head]][i];
}
}
// for(int i=1;i<=n;i++)
// for(int j=1;j<=m;j++)
// cout<<i<<" "<<j<<" "<<d1[i][j]<<endl;
// 注意是向上延伸
for(int i=1;i<=n;i++) //左下角
{
//先找正方形中的最大值
memset(q,0,sizeof(q)); int head=1,tail=0;
for(int j=1;j<=m;j++)
{
while(head<=tail&&j-q[head]>=k) head++;
while(head<=tail&&d1[i][j]>=d1[i][q[tail]]) tail--;
q[++tail]=j;
maxx[i][j]=d1[i][q[head]];
// cout<<i<<" "<<j<<" "<<maxx[i][j]<<endl;
}
memset(q,0,sizeof(q)); head=1,tail=0;
for(int j=1;j<=m;j++)
{
while(head<=tail&&j-q[head]>=k) head++;
while(head<=tail&&d2[i][j]<=d2[i][q[tail]]) tail--;
q[++tail]=j;
minx[i][j]=d2[i][q[head]];
}
}
int ans=INF;
for(int i=k;i<=n;i++)
for(int j=k;j<=m;j++)
ans=min(ans,maxx[i][j]-minx[i][j]);
cout<<ans<<endl;
return 0;
}