现在的位置: 首页 > 综合 > 正文

FZU 2080 二维单调队列

2012年08月11日 ⁄ 综合 ⁄ 共 1694字 ⁄ 字号 评论关闭

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;
}

抱歉!评论已关闭.