题目:点这里

题意:给出一个n*m的矩阵,然后又Q个询问:每个询问有x1,y1,x2,y2,x1,y1为子矩阵的左上角坐标,x2,y2为右上角的坐标。求此子矩阵中元素最大值,判断最大值是否在子矩阵四个角上,在就输出yes,否则输出no。

分析:二维RMQ直接上代码。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int max_=301;
int dp[max_][max_][9][9];//RMQ的递推数组。1,3维是行,2 4维是列。
int a[max_][max_];
void RMQ_init(int n,int m)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)//初始化
    {
        dp[i][j][0][0]=a[i][j];
    }
    for(int i=0;(1<<i)<=n;i++)
        for(int j=0;(1<<j)<=m;j++)
        if(i||j)//i,j不都为0。
    {
        for(int ii=1;ii+(1<<i)-1<=n;ii++)
            for(int jj=1;jj+(1<<j)-1<=m;jj++)
        {
            if(i)//对行递推。
            {
                int k=1<<(i-1);
                dp[ii][jj][i][j]=max(dp[ii][jj][i-1][j],dp[ii+k][jj][i-1][j]);
            }
            else
            {
                int k=1<<(j-1);
                dp[ii][jj][i][j]=max(dp[ii][jj][i][j-1],dp[ii][jj+k][i][j-1]);
            }
        }
    }
}
int RMQ_Q(int x1,int y1,int x2,int y2)//查询
{
    int k1=0;
    while((1<<(k1+1))<=x2-x1+1)k1++;
    int k2=0;
    while((1<<(k2+1))<=y2-y1+1)k2++;
    x2=x2-(1<<k1)+1;
    y2=y2-(1<<k2)+1;
    return max(max(dp[x1][y1][k1][k2],dp[x1][y2][k1][k2]),max(dp[x2][y1][k1][k2],dp[x2][y2][k1][k2]));
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        if(!n&&!m)
            break;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
    {
       scanf("%d",&a[i][j]);
    }
    RMQ_init(n,m);
    int k;
   scanf("%d",&k);
    while(k--)
    {
        int x1,y1,x2,y2;
      scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
       int temp=RMQ_Q(x1,y1,x2,y2);
       printf("%d ",temp);
       if(temp==a[x1][y1]||temp==a[x1][y2]||temp==a[x2][y1]||temp==a[x2][y2])
        printf("yes\n");
       else
        printf("no\n");
    }
}
}

 

posted on 2018-09-25 22:51  海苔  阅读(135)  评论(0编辑  收藏  举报