hdu2888Check Corners(二维RMQ)

题目链接:传送门

题目大意;给定一个n * m的矩阵,再给定q个询问,每次询问(r1,c1)为左上角,(r2,c2)为右下角的子矩形的最大值,并且判断该最大值是否出现在了这个子矩阵的4个顶角上?

思路:二维RMQ模板即可。

注意:此题有两个点需要注意,他会卡内存,所以你要考虑数组的大小,不能开太大。

其次他会卡输入时间,这就很变态了,不能用cin会超时,要改用scanf。

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define maxn 310
int val[maxn][maxn];
int m[maxn];
int dpmax[maxn][maxn][9][9];
//int dpmin[maxn][maxn][10][10];
int n,nn;
void RMQ_init()
{
    //int nlog=(int)(log(double(len))/log(2.0));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=nn;j++)
                //dpmax[i][j][0][0]=dpmin[i][j][0][0]=val[i][j];
                dpmax[i][j][0][0]=val[i][j];
    for(int ii=0;ii<=m[n];ii++)
    {
        for(int jj=0;jj<=m[nn];jj++)
        {
            if(ii+jj)
            {
                for(int i=1;i+(1<<ii)-1<=n;i++)
                {
                    for(int j=1;j+(1<<jj)-1<=nn;j++)
                    {
                        if(ii)
                        {
                           // dpmin[i][j][ii][jj]=min(dpmin[i][j][ii-1][jj],dpmin[i+(1<<(ii-1))][j][ii-1][jj]);
                            dpmax[i][j][ii][jj]=max(dpmax[i][j][ii-1][jj],dpmax[i+(1<<(ii-1))][j][ii-1][jj]);
                        }
                        else
                        {
                          //  dpmin[i][j][ii][jj]=min(dpmin[i][j][ii][jj-1],dpmin[i][j+(1<<(jj-1))][ii][jj-1]);
                            dpmax[i][j][ii][jj]=max(dpmax[i][j][ii][jj-1],dpmax[i][j+(1<<(jj-1))][ii][jj-1]);
                        }
                    }
                }
            }
        }
    }
}
int RMQ_Query(int x1,int y1,int x2,int y2)
{
   int k1=m[x2-x1+1];
   int k2=m[y2-y1+1];
   x2=x2-(1<<k1)+1;
   y2=y2-(1<<k2)+1;
   int ma=max(max(dpmax[x1][y1][k1][k2],dpmax[x1][y2][k1][k2]),max(dpmax[x2][y1][k1][k2],dpmax[x2][y2][k1][k2]));
 //  int mi=min(min(dpmin[x1][y1][k1][k2],dpmin[x1][y2][k1][k2]),min(dpmin[x2][y1][k1][k2],dpmin[x2][y2][k1][k2]));
   return ma;
}

int main()
{
    m[0]=-1;
    for(int i=1;i<305;i++)
    {
        m[i]=((i&(i-1))==0)?m[i-1]+1:m[i-1];
    }
    int b,k;
    while(~scanf("%d%d",&n,&nn))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=nn;j++)
            {
                cin>>val[i][j];
            }
        }
        RMQ_init();
        scanf("%d",&k);
        while(k--)
        {
            int x1,x2,y1,y2;
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            if(x1>x2)swap(x1,x2);
            if(y1>y2)swap(y1,y2);
            int tmp=RMQ_Query(x1,y1,x2,y2);
            printf("%d ",tmp);
            if(tmp == val[x1][y1] || tmp == val[x1][y2] || tmp == val[x2][y1] || tmp == val[x2][y2])
                printf("yes\n");
            else printf("no\n");
        }
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值