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\n");
66             else
67                 printf ("no\n");
68 
69         }
70     }
71     return 0;
72 }

 

posted @ 2015-09-07 16:11  罗茜  阅读(269)  评论(0编辑  收藏  举报