单调队列:最强高度差

先说一下单调队列吧!      单调队列,就是一个符合单调性质的队列,它同时具有单调的性质以及队列的性质。他在编程中使用频率不高,但却占有至关重要的地位。它的作用很简单,就是为了维护一组单调数据,让我们在运行的过程中能够快速寻求前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;
}

 

posted @ 2017-09-25 11:15  star_eternal  阅读(275)  评论(0编辑  收藏  举报