• Hdu 2888 Check Corners (二维RMQ (ST))


    题目链接:

      Hdu 2888 Check Corners

    题目描述:

      给出一个n*m的矩阵,问以(r1,c1)为左上角,(r2,c2)为右下角的子矩阵中最大的元素值是否为子矩阵的顶点?

    解题思路:

      二维区间最值查询,可以用二维的ST算法,dp[x][y][i][j]表示x轴上[x,x+(1<<i)-1]与y轴上[y-(1<<j)+1,y]组成的子矩阵中的最值。预处理的时候处理出来子矩阵的最值,查询的时候对于x,y轴上的查询区间[m, n],都要找到一个k,k满足 n-m+1 < 2^(k+1),假设x轴上为k1,y轴上为k2,然后把x轴上[r1,r2]分为[r1, r1+(1<<k1)-1]与[r2-(1<<k1)+1, r2],y轴类似。根据对x,y轴的划分把查询子矩阵分成4部分,然后选取4部分中的最值即可。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxn = 305;
     8 int dmax[maxn][maxn][9][9];
     9 int arr[maxn][maxn], LOG[maxn];
    10 
    11 void init_RMQ (int n, int m)
    12 {
    13     LOG[0] = -1;
    14     for (int i=1; i<maxn; i++)
    15         LOG[i] = i&(i-1)?LOG[i-1]:LOG[i-1]+1;
    16 
    17     for (int i=1; i<=n; i++)
    18         for (int j=1; j<=m; j++)
    19             dmax[i][j][0][0] = arr[i][j];
    20 
    21     for (int i=0; i<=LOG[n]; i++)
    22         for (int j=0; j<=LOG[m]; j++)
    23         {
    24             if (i==0 && j==0)   continue;
    25             
    26             for (int row=1; row+(1<<i)-1<=n; row++)
    27                 for (int col=1; col+(1<<j)-1<=m; col++)
    28                     if (i == 0)
    29                         dmax[row][col][i][j] = max (dmax[row][col][i][j-1], dmax[row][col+(1<<(j-1))][i][j-1]);
    30                     else
    31                         dmax[row][col][i][j] = max (dmax[row][col][i-1][j], dmax[row+(1<<(i-1))][col][i-1][j]);
    32         }
    33 }
    34 int ST (int x1, int y1, int x2, int y2)
    35 {//(x1,y1)为左上角,(x2,y2)为右下角
    36     int k1 = LOG [x2 - x1 + 1];
    37     int k2 = LOG [y2 - y1 + 1];
    38     int mm1 = dmax [x1][y1][k1][k2];
    39     int mm2 = dmax [x1][y2-(1<<k2)+1][k1][k2];
    40     int mm3 = dmax [x2-(1<<k1)+1][y1][k1][k2];
    41     int mm4 = dmax [x2-(1<<k1)+1][y2-(1<<k2)+1][k1][k2];
    42     return max (max (mm1, mm2), max (mm3, mm4));
    43 }
    44 
    45 int main ()
    46 {
    47     int n, m;
    48     while (scanf ("%d %d", &n, &m) != EOF)
    49     {
    50         for (int i=1; i<=n; i++)
    51             for (int j=1; j<=m; j++)
    52                 scanf ("%d", &arr[i][j]);
    53 
    54         init_RMQ(n, m);
    55 
    56         int x1, y1, x2, y2, q, ans;
    57         scanf ("%d", &q);
    58         while (q --)
    59         {
    60             scanf ("%d %d %d %d", &x1, &y1, &x2, &y2);
    61             ans = ST (x1, y1, x2, y2);
    62             printf ("%d ", ans);
    63 
    64             if (arr[x1][y1]==ans||arr[x1][y2]==ans||arr[x2][y1]==ans||arr[x2][y2]==ans)
    65                 printf ("yes
    ");
    66             else
    67                 printf ("no
    ");
    68 
    69         }
    70     }
    71     return 0;
    72 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    获取指定包下所有自定义注解
    Java中的24种设计模式与7大原则
    学习 Spring Boot:(二十九)Spring Boot Junit 单元测试
    学习Spring Boot:(二十八)Spring Security 权限认证
    学习Spring Boot:(二十七)Spring Boot 2.0 中使用 Actuator
    学习Spring Boot:(二十六)使用 RabbitMQ 消息队列
    学习Spring Boot:(二十五)使用 Redis 实现数据缓存
    学习Spring Boot:(二十四)多数据源配置与使用
    学习Spring Boot:(二十三)Spring Boot 中使用 Docker
    学习Spring Boot:(二十二)使用 AOP
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4789145.html
Copyright © 2020-2023  润新知