Hdu 2888 Check Corners (数据结构_二维RMQ)

 

Hdu 2888 Check Corners (数据结构_二维RMQ)

分类: 全部博客 ACM_好题经典题   264人阅读  评论(0)  收藏  举报

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2888


题目大意给定一个n * m的矩阵,再给定q个询问,每次询问(r1,c1)为左上角,(r2,c2)为右下角的子矩形的最大值。


解题思路很常规的二维RMQ查询最大值。第一次写二维rmq,现在来理下思路。                                                                                                                                                                   二维RMQ是一维RMQ的简单拓展,从一维变成二维,时空复杂度都变高了,但核心思想思想不变,都是倍增的思想。                                                                                                     构造RMQ数组 Create(int n,int m,int b[][]) O(n*m*log(n)*log(m))算法复杂度
      dp[row][col][i][j] 表示 行从row ->row +2^i-1 列从col ->col +2^j-1 二维区间里最大值
      dp[row][col][i][j] = 下行
      max{dp[row][col][i][j-1],dp[row][col][i-1][j],dp[row][col+2^(j-1)][i][j-1],dp[row+2^(i-1)][col][i-1][j]}
     查询RMQ rmq(int sx,int ex,int sy,int ey)
     同一维的将sx->ex 分为两个2^kx区间 将 sy->ey分为两个2^ky的区间
      kx=(int)log2(ex-sx+1) ky=(int)log2(ey-sy+1)
     查询结果为
      max{dp[sx][sy][kx][ky],dp[sx][ey-2^ky+1][kx][ky],dp[ex-2^kx+1][sy][kx][ky],dp[ex-2^kx+1][ey-2^ky+1][kx][ky]}


测试数据:

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


C艹代码:

[cpp]  view plain copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #define MAX 301  
  4. #define max(a,b) ((a)>(b)?(a):(b))  
  5.   
  6.   
  7. int flag,power[MAX];  
  8. int n,m,q,arr[MAX][MAX];  
  9.   
  10.   
  11. struct RMQ{  
  12.   
  13.     int dp[MAX][MAX][9][9];  
  14.     void Create();  
  15.     int Query(int rowl,int rowr,int col,int cor);  
  16. }rmq;  
  17. void RMQ::Create() {  
  18.   
  19.     int i,j,k,s,limitn,limitm;  
  20.     for (i = 1; i <= n; ++i)  
  21.         for (j = 1; j <= m; ++j)  
  22.             dp[i][j][0][0] = arr[i][j];  
  23.       
  24.       
  25.     for (i = 0; i <= power[n]; ++i)  
  26.         for (j = 0; j <= power[m]; ++j) {  
  27.               
  28.             if (i == 0 && j == 0) continue;  
  29.             limitn = n + 1 - (1<<i);  
  30.             limitm = m + 1 - (1<<j);  
  31.             for (k = 1; k <= limitn; ++k)  
  32.                 for (s = 1; s <= limitm; ++s) {  
  33.                       
  34.                     if (i == 0)  
  35.                         dp[k][s][i][j] = max(dp[k][s][i][j-1],dp[k][s+(1<<(j-1))][i][j-1]);  
  36.                     else   
  37.                         dp[k][s][i][j] = max(dp[k][s][i-1][j],dp[k+(1<<(i-1))][s][i-1][j]);  
  38.                           
  39.                 }  
  40.         }  
  41. }  
  42. int RMQ::Query(int r1, int r2, int c1, int c2) {  
  43.   
  44.     int temp = 0;  
  45.     int rk = power[r2-r1+1];  
  46.     int ck = power[c2-c1+1];  
  47.   
  48.   
  49.     temp = max(temp,dp[r1][c1][rk][ck]);  
  50.     temp = max(temp,dp[r1][c2-(1<<ck)+1][rk][ck]);  
  51.     temp = max(temp,dp[r2-(1<<rk)+1][c1][rk][ck]);  
  52.     temp = max(temp,dp[r2-(1<<rk)+1][c2-(1<<ck)+1][rk][ck]);  
  53.      
  54.   
  55.     if (temp == arr[r1][c1] || temp == arr[r2][c1]  
  56.             || temp == arr[r1][c2] || temp == arr[r2][c2])  
  57.         flag = 1;  
  58.     return temp;  
  59. }  
  60. void input (int &a) {  
  61.   
  62.     char c, f;  
  63.     while (((c = getchar()) < '0' || f > '9') );  
  64.     for (a = 0; c >= '0' && c <= '9'; c = getchar())a = a * 10 + c - '0';  
  65. }  
  66.   
  67. int main()  
  68. {  
  69.     int i,j,k = 0;  
  70.     int t,a,b,c,d;  
  71.     for (i = 1; i <= 300; ++i)  
  72.         if (i < (1<<k)) power[i] = k - 1;  
  73.         else power[i] = k,k++;  
  74.   
  75.   
  76.     while (scanf("%d%d",&n,&m) != EOF) {  
  77.   
  78.         for (i = 1; i <= n; ++i)  
  79.             for (j = 1; j <= m; ++j)  
  80.                 input(arr[i][j]);//scanf("%d",&arr[i][j]);  
  81.   
  82.   
  83.         rmq.Create();  
  84.         //scanf("%d",&q);  
  85.         input(q);  
  86.         while (q--) {  
  87.   
  88.             input(a),input(b);  
  89.             input(c),input(d);  
  90.             //scanf("%d%d%d%d",&a,&b,&c,&d);  
  91.             flag = 0;  
  92.             k = rmq.Query(a,c,b,d);  
  93.             if (flag) printf("%d yes\n",k);  
  94.             else printf("%d no\n",k);  
  95.         }  
  96.     }  

你可能感兴趣的:(全部博客,ACM_好题经典题)