[USACO]玉米实验(单调队列)

Description

约翰决定培育新的玉米品种以提高奶牛的产奶效率。约翰所有的土地被分成 N ×N 块,其中第 r行第 c 列的玉米质量为 Ar,c。他打算找一块质量比较均匀的土地开始自己的实验。经过前期考察,他已经锁定了 K 片区域作为实验基地的候选,其中第 i 片区域是从 Ri 行 Ci 列开始,到 Ri + B − 1 行Ci +B −1 列结束的一个 B ×B 的区域。请帮助约翰计算一下,在这些候选区域里,玉米的最高质量与最低质量之差分别是多少。

Input Format

• 第一行:三个整数 N,B 和 K,1 ≤ B ≤ N ≤ 250,1 ≤ K ≤ 10^5

• 第二行到 N +1 行:第 i+1 行有 N 个整数,分别表示 Ai,1 到 Ai,N,对所有 1 ≤ j ≤ N,满足0 ≤ Ai,j ≤ 250

• 第 N + 2 行到第 N + K + 1 行:第 N + i + 1 行有两个整数 Ri 和 Ci,1 ≤ Ri,Ci ≤ N

Output Format

• 第一行到第 K 行:第 i 行表示第 i 片候选区域中最高质量与最低质量之差

Solution

显然的单调队列,\(mx[i][j]\)表示第\(i\)行区间\([j-b,j]\)的最大值,\(mi[i][j]\)同理,写个单调队列即可,

时间复杂度\(O(n^2)\),

Code

#include <cstdio>
#include <algorithm>
#include <list> 
#define N 260
using namespace std;

list<int> Qmx,Qmi;
int n,b,k,A[N],mx[N][N],mi[N][N];

inline int read() {
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch = getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch = getchar();}
	return x*f;
}

int main(){
	n=read(),b=read(),k=read();
	for(int i=1;i<=n;++i){
		Qmx.clear();Qmi.clear();
		for(int j=1;j<=n;++j){
			A[j]=read();
			while(!Qmx.empty()&&A[Qmx.back()]<=A[j]) Qmx.pop_back();
			Qmx.push_back(j);
			while(!Qmx.empty()&&Qmx.front()<=j-b) Qmx.pop_front();
			mx[i][j]=A[Qmx.front()];
			
			while(!Qmi.empty()&&A[Qmi.back()]>=A[j]) Qmi.pop_back();
			Qmi.push_back(j);
			while(!Qmi.empty()&&Qmi.front()<=j-b) Qmi.pop_front();
			mi[i][j]=A[Qmi.front()];
		}
	}
	
	while(k--){
		int x=read(),y=read(); 
		int Max=-1e9,Min=1e9;
		for(int i=x;i<=x+b-1;++i){
			Max=max(Max,mx[i][y+b-1]);
			Min=min(Min,mi[i][y+b-1]);
		} 
		printf("%d\n",Max-Min);
	}
	return 0;
}
posted @ 2017-11-07 10:30  void_f  阅读(359)  评论(0编辑  收藏  举报