二维RMQ

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int N = 300 + 2;
int dp[N][N][9][9];
void RMQ_inin(int m, int n){//维护M行N列的矩阵,其实都是倍增的思想,对比线段树是二分构建,相反思维
    int kr=int(log(double(m))/log(2.0));//判断x轴长度的最大的倍增的次数(2^kr)
    int kc=int(log(double(n))/log(2.0));//判断y轴长度的最大的倍增的次数(2^kc)
    for(int i = 0; i <= kr; i++)
        for(int j = 0; j <= kc; j++){
            if(!i && !j)continue;//当i和j都为零时,既是都不倍增,为初始值
            for(int r = 1; r+(1<<i)-1 <= m; r++)//r+(1<<i)-1 为从r开始2^i长度的最后一个值, 用来判断是否把所有的元素都遍历完
                for(int c = 1; c+(1<<j)-1 <= n; c++){//c+(1<<j)-1 为c开始2^j长度的最后一个值, 用来判断是否把所有的元素都遍历完
                    if(!i)dp[r][c][i][j]=max(dp[r][c][i][j-1],dp[r][c+(1<<(j-1))][i][j-1]);//求区间j到2^j的最大值
                    else dp[r][c][i][j]=max(dp[r][c][i-1][j],dp[r+(1<<(i-1))][c][i-1][j]);//求区间i到2^i的最大值
                }
        }//我来解释一下dp[r][c][i][j]:从r行起往后延伸2^i行,从c列起往后延伸2^j列找表示的区域,的最值
}
int RMQ(int x1, int y1, int x2, int y2){  //求出区间最值
    int kr = int(log(double(x2-x1+1))/log(2.0));
    int kc = int(log(double(y2-y1+1))/log(2.0));
    int t1 = dp[x1][y1][kr][kc];
    int t2 = dp[x2-(1<<kr)+1][y1][kr][kc];
    int t3 = dp[x1][y2-(1<<kc)+1][kr][kc];
    int t4 = dp[x2-(1<<kr)+1][y2-(1<<kc)+1][kr][kc];
    return max(max(t1, t2), max(t3, t4));
}
int main(){
    int n, m, x1, y1, x2, y2, Q;
    while(~scanf("%d%d", &m, &n)){//输入行列数
        for(int i = 1; i <= m; i++)//扫行
            for(int j = 1; j <= n; j++)//扫列
                scanf("%d", &dp[i][j][0][0]);//初始输入三四维都是零
        RMQ_inin(m, n);//数据结构构建维护最值
        scanf("%d", &Q);//Q个询问
        while(Q--){
            scanf("%d%d%d%d", &x1, &y1, &x2, &y2);//给出左上角与右下角
            int maxn = RMQ(x1, y1, x2, y2);//数据结构查询最值
            if(maxn==dp[x1][y1][0][0] || maxn==dp[x1][y2][0][0] || maxn==dp[x2][y1][0][0] || maxn==dp[x2][y2][0][0])
                printf("%d %s\n", maxn, "yes");//有相同就Y
            else printf("%d %s\n", maxn, "no");//没有就N
        }
        memset(dp, 0, sizeof(dp));//多组样例全清空
    }
    return 0;
}

HDU2888(二维RMQ)
Sample Input
4 4
4 4 10 7
2 13 9 11
5 7 8 20
13 20 8 2
4
1 1 4 4
1 1 3 3
1 3 3 4
1 1 1 1
Sample Output
20 no
13 no
20 yes
4 yes

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值