单调队列:最强高度差
先说一下单调队列吧! 单调队列,就是一个符合单调性质的队列,它同时具有单调的性质以及队列的性质。他在编程中使用频率不高,但却占有至关重要的地位。它的作用很简单,就是为了维护一组单调数据,让我们在运行的过程中能够快速寻求前k个或后k个中最大或最小的值。
我们从题入手;
时间限制:3.0s 空间限制:64.0MB
问题描述
我们把一块山地划分为N x N的小块。你已经知道了每一块地的海拔高度。你需要回答若干个询问。一次询问指定了一块S x S的正方形区域(S是一个已经给定的值),你需要回答出在这个区域里最小海拔高度和最大海拔高度相差多少。
输入数据
第一行输入三个用空格隔开的正整数n,s,k,表示山地的大小、一次询问的大小和询问的次数。输入数据保证s<=n。
以下n行为一个N x N的矩阵,该矩阵描述了这个山地的高度情况。这些数字保证是不超过maxint的正整数。
接下来k行每行两个数x,y,询问以第x行第y列的格子作为左上角的S x S的方格中最大的高度差。输入数据保证输入的x,y有意义。
输出数据
对于每一个询问,输出询问的区域中高度差的最大值。
样例输入
5 3 1
5 1 2 6 3
1 3 5 2 7
7 2 4 6 1
9 9 8 6 5
0 6 9 3 9
1 2
样例输出
5
样例说明
输入数据询问子矩阵:
1 2 6
3 5 2
2 4 6
的最大高度差是多少。
答案为6-1=5。
数据规模
对于100%的数据,n<=2000,k<=10000。
这道题的数据看,模拟暴力肯定要爆,我们就想到了单调队列,求出每一行限宽的的最小值,这里,我再强调单调队列的作用:让我们在运行的过程中能够快速寻求前k个或后k个中最大或最小的值。
至于操作,这就是一个单调队列裸题,代码就是操作(*^▽^*)
http://blog.csdn.net/justmeh/article/details/5844650
#include<cstdio> #include<cstring> #define N 2000+10 using namespace std; int data[N][N],max[N][N],min[N][N]; struct ap { int val,pos; }tep[N]; int main() { int n,s,k; scanf("%d%d%d",&n,&s,&k); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&data[i][j]); for(int i=1;i<=n;i++) { int cl=1,op=1; max[i][1]=tep[cl].val=data[i][1]; tep[cl].pos=1; for(int j=2;j<=n;j++) { while(data[i][j]>tep[op].val&&cl<=op) op--; tep[++op].val=data[i][j]; tep[op].pos=j; while(j-tep[cl].pos>=s) cl++; max[i][j]=tep[cl].val; } } for(int i=1;i<=n;i++) { int cl=1,op=1; min[i][1]=tep[cl].val=data[i][1]; tep[cl].pos=1; for(int j=2;j<=n;j++) { while(data[i][j]<tep[op].val&&cl<=op) op--; tep[++op].val=data[i][j]; tep[op].pos=j; while(j-tep[cl].pos>=s) cl++; min[i][j]=tep[cl].val; } } int x,y; for(int i=1;i<=k;i++) { scanf("%d%d",&x,&y); int Min=999999999,Max=-999999999; for(int i=x;i<x+s;i++) { if(max[i][y+s-1]>Max) Max=max[i][y+s-1]; if(min[i][y+s-1]<Min) Min=min[i][y+s-1]; } printf("%d\n",Max-Min); } return 0; }