问题 D: [HAOI2007]理想的正方形
时间限制: 10 Sec 内存限制: 162 MB题目描述
有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值
的差最小。
输入
第一行为3个整数,分别表示a,b,n的值第二行至第a+1行每行为b个非负整数,表示矩阵中相应位置上的数。每
行相邻两数之间用一空格分隔。
100%的数据2<=a,b<=1000,n<=a,n<=b,n<=100
输出
仅一个整数,为a*b矩阵中所有“n*n正方形区域中的最大整数和最小整数的差值”的最小值。
样例输入
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
样例输出
1
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#define maxn 1007
#define LL long long
using namespace std;
LL e,f,a[maxn],c[maxn],mp3[maxn],head3,tail3,mp1[maxn],mp2[maxn],b[maxn][maxn],w[maxn][maxn],head1,tail1,head2,tail2,n,k;
inline int read()
{
int s=0,f=1;
char ch=getchar();
while(ch>'9'||ch<'0')
{
if(ch=='-')f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
s=s*10+ch-'0';
ch=getchar();
}
return s*f;
}
inline void push1(int i)
{
while(tail1>head1&&a[i]>a[mp1[tail1-1]])
tail1--;
mp1[tail1++]=i;
}
inline void push3(int i)
{
while(tail3>head3&&c[i]<c[mp3[tail3-1]])
tail3--;
mp3[tail3++]=i;
}
inline void push2(int i)
{
while(tail2>head2&&a[i]<a[mp2[tail2-1]])
tail2--;
mp2[tail2++]=i;
}
int main()
{
//memset(a,0x3f,sizeof(a));
//freopen("in.txt","r",stdin);//freopen("out.ans","w",stdout);
//freopen("square.in","r",stdin);freopen("square.out","w",stdout);
cin>>e>>f>>n;
int z,q=0;
k=n;
for(int i=1;i<=e;i++)
{
head1=0;
tail1=0;
head2=0;
tail2=0;
memset(a,0,sizeof(a));
memset(mp1,0,sizeof(mp1));
memset(mp2,0,sizeof(mp2));
for(int j=1;j<=f;j++)
{
cin>>a[j];
//cout<<a[i]<<" ";
push1(j);
push2(j);
if(j>=k)
{
z=j-k;
while(mp1[head1]<=z)
head1++;
while(mp2[head2]<=z)
head2++;
w[i][j]=a[mp2[head2]];
b[i][j]=a[mp1[head1]];
}
}
//cout<<endl;
}
memset(mp1,0,sizeof(mp1));
memset(mp2,0,sizeof(mp2));
LL ans=999999999;
for(int j=n;j<=f;j++)
{
head1=0;
tail1=0;
head3=0;
tail3=0;
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
memset(mp1,0,sizeof(mp1));
memset(mp3,0,sizeof(mp3));
for(int i=1;i<=e;i++)
{
a[i]=b[i][j];
c[i]=w[i][j];
//cout<<a[i]<<" "<<c[i]<<" ii"<<i<<endl;
push1(i);
push3(i);
if(i>=k)
{
z=i-k;
while(mp1[head1]<=z)
head1++;
while(mp3[head3]<=z)
head3++;
ans=min(ans,a[mp1[head1]]-c[mp3[head3]]);
}
}
}
cout<<ans;
//while(1);
return 0;
}