• HDU 2888 Check Corners (模板题)【二维RMQ】


    <题目链接>

    <转载于 >>> >

    题目大意:

    给出一个N*M的矩阵,并且给出该矩阵上每个点对应的值,再进行Q次询问,每次询问给出代询问子矩阵的左上顶点和右下顶点,问该子矩阵的最大值是多少,并且判断该最值是否在该子矩阵的四个顶角上。

    解题分析:

    很明显求二维区间内的最值,需要用到二维RMQ,其中dp[i][j][k][l]表示左上角为(i,j),右下角为(i + 2 ^ k - 1, j + 2 ^ l - 1)这个矩形内的最值。注意这个四维数组不要开得太大,否则容易MLE。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4  
     5 using namespace std;
     6 const int maxn = 305;
     7  
     8 int n, m, q, val[maxn][maxn], dp[maxn][maxn][9][9];   //dp[i][j][k][l]表示左上角为(i,j),右下角为(i + 2 ^ k - 1, j + 2 ^ l - 1)这个矩形内的最值
     9  
    10 void rmq_init(int n, int m){
    11     for (int i = 1; i <= n; i++) {
    12         for (int j = 1; j <= m; j++)
    13             dp[i][j][0][0] = val[i][j];
    14     }
    15  
    16     for (int x = 0; (1<<x) <= n; x++)
    17         for (int y = 0; (1<<y) <= m; y++)
    18             if (x + y){
    19                 for (int i = 1; i + (1<<x) - 1 <= n; i++)
    20                     for (int j = 1; j + (1<<y) - 1 <= m; j++) {
    21                         if (x)   //在y轴方向比较
    22                             dp[i][j][x][y] = max(dp[i][j][x-1][y], dp[i+(1<<(x-1))][j][x-1][y]);
    23                         else   //在x轴方向比较
    24                             dp[i][j][x][y] = max(dp[i][j][x][y-1], dp[i][j+(1<<(y-1))][x][y-1]);
    25                     }
    26             }
    27 }
    28  
    29 int rmq_query(int x1, int y1, int x2, int y2) {
    30     int x = 0, y = 0;
    31     while ((1<<(x+1)) <= x2 - x1 + 1) x++;
    32     while ((1<<(y+1)) <= y2 - y1 + 1) y++;
    33     x2 = x2 - (1<<x) + 1;
    34     y2 = y2 - (1<<y) + 1;
    35  
    36     return max( max(dp[x1][y1][x][y], dp[x2][y1][x][y]), max(dp[x1][y2][x][y], dp[x2][y2][x][y]));
    37 }
    38  
    39 int main () {
    40     while (scanf("%d%d", &n, &m) == 2) {
    41         for (int i = 1; i <= n; i++) {
    42             for (int j = 1; j <= m; j++)
    43                 scanf("%d", &val[i][j]);
    44         }
    45         rmq_init(n, m);
    46  
    47         scanf("%d", &q);
    48         int x1, y1, x2, y2;
    49         while (q--) {
    50             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
    51             int ans = rmq_query(x1, y1, x2, y2);
    52             bool flag = false;
    53             if (ans == val[x1][y1] || ans == val[x1][y2] || ans == val[x2][y1] || ans == val[x2][y2])   //检查最值是否在子矩阵的四个顶角上
    54                 flag = true;
    55             printf("%d %s
    ", ans, flag ? "yes" : "no");
    56         }
    57     }
    58     return 0;
    59 }

    2018-10-20

  • 相关阅读:
    欢迎使用CSDN-markdown编辑器
    银行票据
    【思考】:怎样把论文按照一定格式生成模板?
    ARP地址解析协议
    ACL访问控制列表
    dns域名系统
    NAT网络地址转换
    MAC地址如何在windows与unix下查看?
    银行承兑汇票的推广与使用给中国企业带来的影响?
    win7 复制文件慢的解决方法
  • 原文地址:https://www.cnblogs.com/00isok/p/9821253.html
Copyright © 2020-2023  润新知