BZOJ 1047 理想的正方形

可以先合一维再合一维

两个方向单调队列分别搞一下即可

蒟蒻我居然想不到单调队列

#include <cstdio>

const int MAXN=1011;
const int MAXM=1011;
const int INF=1034567890;

int N, M, K;
int Map[MAXN][MAXM], Temp[MAXN][MAXM], Max[MAXN][MAXM], Min[MAXN][MAXM];

int Q[MAXN+MAXM], Head, Tail;

int main(){
	
	scanf("%d%d%d", &N, &M, &K);
	for(int i=1;i<=N;++i)
		for(int j=1;j<=M;++j)
			scanf("%d", &Map[i][j]);
	
	for(int i=1;i<=N;++i){
		Head=1;Tail=1;
		for(int j=1;j<=M;++j){
			while(Head<Tail && Map[i][Q[Tail-1]]<=Map[i][j])	--Tail;
			Q[Tail++]=j;
			while(Q[Head]<=j-K)	++Head;
			Temp[i][j]=Map[i][Q[Head]];
		}
	}
	
	for(int j=1;j<=M;++j){
		Head=1;Tail=1;
		for(int i=1;i<=N;++i){
			while(Head<Tail && Temp[Q[Tail-1]][j]<=Temp[i][j])	--Tail;
			Q[Tail++]=i;
			while(Q[Head]<=i-K)	++Head;
			Max[i][j]=Temp[Q[Head]][j];
		}
	}
	
	for(int i=1;i<=N;++i){
		Head=1;Tail=1;
		for(int j=1;j<=M;++j){
			while(Head<Tail && Map[i][Q[Tail-1]]>=Map[i][j])	--Tail;
			Q[Tail++]=j;
			while(Q[Head]<=j-K)	++Head;
			Temp[i][j]=Map[i][Q[Head]];
		}
	}
	
	for(int j=1;j<=M;++j){
		Head=1;Tail=1;
		for(int i=1;i<=N;++i){
			while(Head<Tail && Temp[Q[Tail-1]][j]>=Temp[i][j])	--Tail;
			Q[Tail++]=i;
			while(Q[Head]<=i-K)	++Head;
			Min[i][j]=Temp[Q[Head]][j];
		}
	}
	
	for(int i=1;i<=N;++i)
		for(int j=1;j<=M;++j)
			Temp[i][j]=Max[i][j]-Min[i][j];
	
	int ANS=INF;
	
	for(int i=K;i<=N;++i)
		for(int j=K;j<=M;++j)
			if(Temp[i][j]<ANS)	ANS=Temp[i][j];
	
	printf("%d\n", ANS);
	
	return 0;
}

/*
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2

1

*/
posted @ 2018-06-11 23:13  Pickupwin  阅读(194)  评论(0编辑  收藏  举报