【HAOI2007】理想的正方形(单调队列)

首先预处理出pre_xmax[i][j],表示第i横行,第j~j+N-1竖列a[i][j]的最大值;预处理出pre_xmin,意义与前边相反。

接着处理pre_max[i][j]表示第i横行,第j~j+N-1竖列pre_xmax[i][j]的最大值;预处理出pre_min,意义与前边相反。

处理完后,pre_max[i][j]实际上是a[i~i+N-1][j~j+N-1]里的最大值,pre_min类似,以i,j为左上角。

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1005;
int A,B,N,a[MAXN][MAXN];
int pre_xmin[MAXN][MAXN],pre_xmax[MAXN][MAXN];
int pre_min[MAXN][MAXN],pre_max[MAXN][MAXN];
struct data{int id,num;}q[MAXN];

char c;
void scan(int &x)
{
	for(c=getchar();c<'0'||c>'9';c=getchar());
	for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}

void prexmax(int x)
{
	int L=1,R=0,i;
	q[1]=((data){0,0});
	for(i=B;i>=1;i--)
	{
		while(L<=R&&q[L].id-i>=N) L++;
		while(L<=R&&a[x][i]>=q[R].num) R--;
		q[++R]=((data){i,a[x][i]});
		pre_xmax[x][i]=q[L].num;
	}
}

void prexmin(int x)
{
	int L=1,R=0,i;
	q[1]=((data){0,0});
	for(i=B;i>=1;i--)
	{
		while(L<=R&&q[L].id-i>=N) L++;
		while(L<=R&&a[x][i]<=q[R].num) R--;
		q[++R]=((data){i,a[x][i]});
		pre_xmin[x][i]=q[L].num;
	}
}

void premax(int x) 
{
	int L=1,R=0,i;
	q[1]=((data){0,0});
	for(i=A;i>=1;i--)
	{
		while(L<=R&&q[L].id-i>=N) L++;
		while(L<=R&&pre_xmax[i][x]>=q[R].num) R--;
		q[++R]=((data){i,pre_xmax[i][x]});
		pre_max[i][x]=q[L].num;
	}
}

void premin(int x)
{
	int L=1,R=0,i;
	q[1]=((data){0,0});
	for(i=A;i>=1;i--)
	{
		while(L<=R&&q[L].id-i>=N) L++;
		while(L<=R&&pre_xmin[i][x]<=q[R].num) R--;
		q[++R]=((data){i,pre_xmin[i][x]});
		pre_min[i][x]=q[L].num;
	}
}

int main()
{
	int i,j;
	scan(A);scan(B);scan(N);
	for(i=1;i<=A;i++)
		for(j=1;j<=B;j++)
			scan(a[i][j]);
			
	for(i=1;i<=A;i++)
	{
		prexmax(i);
		prexmin(i);
	}
	for(i=1;i<=B;i++)
	{
		premax(i);
		premin(i);
	}
	
	int ans=0x3f3f3f3f;
	for(i=1;i<=A-N+1;i++)
		for(j=1;j<=B-N+1;j++)
			ans=min(ans,pre_max[i][j]-pre_min[i][j]);
	
	cout<<ans;
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/WWWengine/article/details/82194268