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\n", ans, flag ? "yes" : "no"); 56 } 57 } 58 return 0; 59 }
2018-10-20
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。