题目链接:
题目描述:
给出一个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 }