M - POJ 2019 二维RMQ

FJ has decided to grow his own corn hybrid in order to help the cows make the best possible milk. To that end, he's looking to build the cornfield on the flattest piece of land he can find. 

FJ has, at great expense, surveyed his square farm of N x N hectares (1 <= N <= 250). Each hectare has an integer elevation (0 <= elevation <= 250) associated with it. 

FJ will present your program with the elevations and a set of K (1 <= K <= 100,000) queries of the form "in this B x B submatrix, what is the maximum and minimum elevation?". The integer B (1 <= B <= N) is the size of one edge of the square cornfield and is a constant for every inquiry. Help FJ find the best place to put his cornfield. 

Input

* Line 1: Three space-separated integers: N, B, and K. 

* Lines 2..N+1: Each line contains N space-separated integers. Line 2 represents row 1; line 3 represents row 2, etc. The first integer on each line represents column 1; the second integer represents column 2; etc. 

* Lines N+2..N+K+1: Each line contains two space-separated integers representing a query. The first integer is the top row of the query; the second integer is the left column of the query. The integers are in the range 1..N-B+1. 

Output

* Lines 1..K: A single integer per line representing the difference between the max and the min in each query. 

Sample Input

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

Sample Output

5

题意:给出一个N*N的矩阵,和要求的矩形的边长B,以及K次询问,然后给出一个点(Xi,Yi),输出,在以给出的点为左上角的点,边长为B的子矩阵中,最大值与最小值的差;


选用第一种方法,即矩阵的每一行当作一维RMQ: 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include <map>
#include <queue>
using namespace std;
const int maxn = 500;
int maxx[maxn][maxn][11], minn[maxn][maxn][11], mapp[maxn][maxn], n, m, q, width, high, maxxx, minnn;
void RMQ()
{
    //初始化maxx数组,第i行一维RMQ,从第j个数开始,长度为2^0范围内,其最大值为它本身;
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
            maxx[i][j][0] = minn[i][j][0] = mapp[i][j];
    }
    //第一个for,遍历每一行;第二个for与第三个for相当于一维RMQ中的两个for循环(注意顺序不能颠倒!);
    for(int i=1; i<=n; i++)
    {
        for(int k=1; (1<<k)<=m; k++)//在矩形每一行中一共有m个数,从j开始,长度为1的最大值长度为2的最大值长度为3的最大值等,对k进行限制;
        {
            for(int j=1; j+(1<<k)-1<=m; j++)//对j进行的循环是在k之后;
            {
                maxx[i][j][k] = max(maxx[i][j][k-1], maxx[i][j+(1<<(k-1))][k-1]);
                minn[i][j][k] = min(minn[i][j][k-1], minn[i][j+(1<<(k-1))][k-1]);
            }
        }
    }
}
//输入整个矩形,并且进行RMQ初始化;
void read()
{
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            scanf("%d", &mapp[i][j]);
        }
    }
    RMQ();
}
//查询从(a, b)点开始,横纵长度为withe的范围内的最值,
void ask(int a, int b)
{
    int k = (int )(log(double(width))/log(2.0));
    maxxx = 0, minnn = int(1e9);
    int l = b, r = b+width-1;
    for(int i=a; i<a+high; i++)//对行进行遍历;
    {
        maxxx = max(maxxx, max(maxx[i][l][k], maxx[i][r-(1<<k)+1][k]));//每一行的最大值;
        minnn = min(minnn, min(minn[i][l][k], minn[i][r-(1<<k)+1][k]));//每一行的最小值;
    }
}
//输入每次的询问,并输出结果;
void go()
{
    int a, b;
    for(int i=1; i<=q; i++)
    {
        scanf("%d%d", &a, &b);
        ask(a, b);
        printf("%d\n",maxxx-minnn);
    }
}
int main()
{
    while(scanf("%d%d%d", &n, &width, &q)!=EOF)
    {
        m = n;//n为行数,m为列数;
        high = width;
        read();
        go();
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值