题目传送门
题意解析:
题目就是给了你一个n*m的矩形,然后让你找一个正方形,要求这个正方形中的最大值减去最小值的差值最大
My opinion:看到这题,也许一开始只会n^4的写法,然后稍作优化也许可以变成n^3logn,然后就一脸不会了,但是其实只要仔细想一想,就会发现原来可以用单调队列做,所以我们可以先预处理出每一排的最大值和最小值,之后我们可以通过每一排的单调队列然后直接计算出答案。
总结:
1、输入。
2、用单调队列预处理。
3、单调队列找答案。
4、输出。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 1e18
#define eps 1e-8
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxn=1005;
int a[maxn][maxn],q[maxn],pos[maxn],Max[maxn][maxn],Min[maxn][maxn];
int ans1[maxn],ans2[maxn];
int l,r,n,m,sq;
void init(){
rep(i,1,n){
l=1,r=1;
rep(j,1,m){
while (l<r&&q[r-1]<=a[i][j]) r--;
q[r]=a[i][j];pos[r]=j;r++;
if (pos[l]==j-sq) l++;
if (j>=sq) Max[i][j]=q[l];
}
l=1;r=1;
rep(j,1,m){
while (l<r&&q[r-1]>=a[i][j]) r--;
q[r]=a[i][j];pos[r]=j;r++;
if (pos[l]==j-sq) l++;
if (j>=sq) Min[i][j]=q[l];
}
}
}
void work(){
int ans=INF;
rep(i,sq,m){
l=1,r=1;
rep(j,1,n){
while (l<r&&q[r-1]>=Min[j][i]) r--;
q[r]=Min[j][i];pos[r]=j;r++;
if (pos[l]==j-sq) l++;
if (j>=sq) ans1[j]=q[l];
}
l=1,r=1;
rep(j,1,n){
while (l<r&&q[r-1]<=Max[j][i]) r--;
q[r]=Max[j][i];pos[r]=j;r++;
if (pos[l]==j-sq) l++;
if (j>=sq) ans2[j]=q[l];
}
rep(j,sq,n) ans=min(ans,ans2[j]-ans1[j]);
}
printf("%d\n",ans);
}int main(){
n=read(),m=read(),sq=read();
rep(i,1,n)
rep(j,1,m)
a[i][j]=read();
init();
work();
return 0;
}