hev神让我做做这题...
大概我们可以用一个二维的单调队列来写的。
用两个矩阵来记录大矩阵的部分最值。
例如用A[i][j]来记录mat[i][j]---mat[i+r-1][j]这一列的最小值,用Mi[i][j]来记录A[i][j]--A[i][j+c-1]这一行的最小值,于是乎Mi[i][j]就是mat[i,i+r-1][j,j+c-1]这个r*c的子矩阵的最小值了。
我的代码相当挫
大家都是530++ms AC的 我却要970ms.... 再看看别人的代码...
发现压线过特别有快感啊!
#include<iostream>
#include<string>
#include<cstdio>
#define MN 1111
#define INF 0x7F7F7F7F
#define FF(i,N) for( int i=0;i<N;i++ )
using namespace std;
int mat[MN][MN];
int A[MN][MN],B[MN][MN],Mi[MN][MN],Ma[MN][MN];
int n,m,r,c;
struct node{
int id,v;
}mi[MN],ma[MN];
int hemi,hema;
void insert( int num,int y )
{
while( y-mi[hemi].id>=r&&mi[hemi].v!=INF ) hemi++;
while( y-ma[hema].id>=r&&ma[hema].v!=INF ) hema++;
int i;
for( i=hemi;mi[i].v!=INF;i++ )
if( mi[i].v>num )
break;
mi[i].v=num;
mi[i].id=y;
for( i=hema;ma[i].v!=INF;i++ )
if( ma[i].v<num )
break;
ma[i].v=num;
ma[i].id=y;
}
void insert0( int num,int y )
{
while( y-mi[hemi].id>=c&&mi[hemi].v!=INF ) hemi++;
if( num==INF ) return;
int a=0;
for( a=hemi;mi[a].v!=INF;a++ )
if( mi[a].v>num )
break;
mi[a].v=num;
mi[a].id=y;
}
void insert1( int num,int y )
{
while( y-ma[hema].id>=c&&mi[hema].v!=INF ) hema++;
if( num==INF ) return;
int a=0;
for( a=hema;ma[a].v!=INF;a++ )
if( ma[a].v<num )
break;
ma[a].v=num;
ma[a].id=y;
}
int main()
{
while( scanf("%d%d%d%d",&n,&m,&r,&c)!=EOF )
{
for( int i=1;i<=n;i++ )
for( int j=1;j<=m;j++ )
scanf( "%d",&mat[i][j] );
for( int j=1;j<=m;j++ )
{
memset(mi,0x7F,sizeof(mi));
memset(ma,0x7F,sizeof(ma));
hemi=hema=0;
for( int i=1;i<=n;i++ )
{
insert(mat[i][j],i);
if( i>=r )
{
A[i-r+1][j]=mi[hemi].v;
B[i-r+1][j]=ma[hema].v;
}
}
}
int ans=0;
for( int i=1;i-r+1<n;i++ )
{
memset(mi,0x7F,sizeof(mi));
memset(ma,0x7F,sizeof(ma));
hema=hemi=0;
for( int j=1;j-c+1<m;j++ )
{
insert0( A[i][j],j );
insert1( B[i][j],j );
if( j>=c )
{
Mi[i][j-c+1]=mi[hemi].v;
Ma[i][j-c+1]=ma[hema].v;
ans=max( ans,Ma[i][j-c+1]-Mi[i][j-c+1] );
}
}
}
printf( "%d\n",ans );
}
return 0;
}