lightoj 1081 - Square Queries(二维RMQ)

3 篇文章 0 订阅

Little Tommy is playing a game. The game is played on a 2D N x N grid. There is an integer in each cell of the grid. The rows and columns are numbered from 1 to N.

At first the board is shown. When the user presses a key, the screen shows three integers I, J, S which designates a square (I, J) to (I+S-1, J+S-1) in the grid. The player has to predict the largest integer found in this square. The user will be given points based on the difference between the actual result and the given result.

Tommy doesn't like to lose. So, he made a plan, he will take help of a computer to generate the result. But since he is not a good programmer, he is seeking your help.

Input

Input starts with an integer T (≤ 3), denoting the number of test cases.

The first line of a case is a blank line. The next line contains two integers N (1 ≤ N ≤ 500), Q (0 ≤ Q ≤ 50000). Each of the next N lines will contain N space separated integers forming the grid. All the integers will be between 0 and 105.

Each of the next Q lines will contain a query which is in the form I J S (1 ≤ I, J ≤ N and 1 ≤ I + S, J + S < N and S > 0).

Output

For each test case, print the case number in a single line. Then for each query you have to print the maximum integer found in the square whose top left corner is (I, J) and whose bottom right corner is (I+S-1, J+S-1).

Sample Input

Output for Sample Input

1

 

4 5

67 1 2 3

8 88 21 1

89 12 0 12

5 5 5 5

1 1 2

1 3 2

3 3 2

1 1 4

2 2 3

Case 1:

88

21

12

89

88



题目大意是给你一个n*n的矩阵,然后有q次询问,给你x,y,s,让你求(x,y)到(x+s-1,y+s-1)的矩形里面的数字的最大值。

区间最值查询,很明显是RMQ,在RMQ的基础上改成二维的就可以了。就查询x到x+s-1行中的最大值即可。

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long

using namespace std;

int maxsum[550][550][30];
int a[550];

int main(void)
{
    int T,n,q,i,j;
    scanf("%d",&T);
    int cas = 1;
    while(T--)
    {
        scanf("%d%d",&n,&q);
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf("%d",&a[j]);
                maxsum[i][j][0] =  a[j];//预处理第一层
            }
            for(int r=1;(1<<r)<=n;r++)
                for(int l=1;l + (1<<r) - 1 <= n;l++)
                {
                    maxsum[i][l][r] = max(maxsum[i][l][r - 1], maxsum[i][l + (1 << (r - 1))][r - 1]);
                }
        }
        printf("Case %d:\n",cas++);
        while(q--)
        {
            int x,y,L,R,s;
            int maxn = 0;
            scanf("%d%d%d",&x,&y,&s);
            L = y;
            R = y + s - 1;
            int k = (int)(log(R - L + 1.0)/log(2.0));
            for(i=x;i<=x+s-1;i++)
                maxn = max(maxn,max(maxsum[i][L][k],maxsum[i][R-(1<<k)+1][k]));
            printf("%d\n",maxn);
        }
    }

    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值