标签:
http://www.lydsy.com/JudgeOnline/problem.php?id=1047
对每一行维护一个单调队列,保存在lmin[][],lmax[][]
然后对每一列维护一个单调队列,最后n*n枚举
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define clr(a,b) memset(a,b,sizeof(a))
const int maxn = 1100;
const int INF = 0x3f3f3f3f;
using namespace std;
int n,m,k;
int que[maxn],a[maxn][maxn];
int lmin[maxn][maxn],lmax[maxn][maxn];
int rmin[maxn][maxn],rmax[maxn][maxn];
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif // ONLINE_JUDGE
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]);
}
}
int front,rear;
for(int i=1;i<=n;++i){
front=rear=1;
for(int j=1;j<=m;++j){
while(front<rear&&a[i][que[rear-1]]>a[i][j]) rear--;
que[rear++]=j;
while(front<rear&&j-que[front]+1>k) front++;
if(j>=k) lmin[i][j-k+1]=a[i][que[front]];
}
front=rear=1;
for(int j=1;j<=m;++j){
while(front<rear&&a[i][que[rear-1]]<a[i][j]) rear--;
que[rear++]=j;
while(front<rear&&j-que[front]+1>k) front++;
if(j>=k) lmax[i][j-k+1]=a[i][que[front]];
}
}
for(int j=1;j<=m-k+1;++j){//列
front=rear=1;
for(int i=1;i<=n;++i){//行
while(front<rear&&lmin[que[rear-1]][j]>lmin[i][j]) rear--;
que[rear++]=i;
while(front<rear&&i-que[front]+1>k) front++;
if(i>=k) rmin[j][i-k+1]=lmin[que[front]][j];
}
front=rear=1;
for(int i=1;i<=n;++i){
while(front<rear&&lmax[que[rear-1]][j]<lmax[i][j]) rear--;
que[rear++]=i;
while(front<rear&&i-que[front]+1>k) front++;
if(i>=k) rmax[j][i-k+1]=lmax[que[front]][j];
}
}
int ans=INF;
for(int i=1;i<=m-k+1;++i){
for(int j=1;j<=n-k+1;++j){
if(rmax[i][j]!=-1)
ans=min(ans,rmax[i][j]-rmin[i][j]);
}
}
printf("%d\n",ans);
return 0;
}
1047: [HAOI2007]理想的正方形——二维单调队列
标签:
原文地址:http://blog.csdn.net/u014141559/article/details/46136953