【ybt高效进阶4-3-4】矩阵最值

矩阵最值

题目链接:ybt高效进阶4-3-4

题目大意

给你一个矩阵,多次询问,询问一个子矩阵的数的最大值。

思路

这题可以看出是用二维的 ST 表。

很容易想到,但是实现可以说是非常的恶心。

查询其实还好,主要是合并的地方思维一定要捋清。
而且因为你是矩阵,你合并还要合并两种一条线的情况。(横着一条线,竖着一条线)
因为你是矩阵,你不处理这两个,它后面 DP 合并就无法正常进行。

具体可以看看代码。

代码

#include<cstdio>
#include<iostream>

using namespace std;

int n, m, k, a[251][251];
int f[251][251][11][11];
int log[251], x1, y1, x2, y2;

void get_log() {
    
    //预处理 log
	int now = 1, x = 0;
	while ((now << 1) <= 250) {
    
    
		for (int i = now; i < (now << 1); i++)
			log[i] = x;
		x++;
		now <<= 1;
	}
	while (now <= 250) {
    
    
		log[now++] = x;
	}
}

int main() {
    
    
	get_log();
	
	scanf("%d %d %d", &n, &m, &k);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++) {
    
    
			scanf("%d", &a[i][j]);
			f[i][j][0][0] = a[i][j];
		}
	
	for (int j = 1; j <= log[m]; j++)//处理横着一根线的
		for (int ii = 1; ii <= n; ii++)
			for (int jj = 1; jj <= m; jj++) {
    
    
				f[ii][jj][0][j] = f[ii][jj][0][j - 1];
				if (jj + (1 << (j - 1)) <= m) f[ii][jj][0][j] = max(f[ii][jj][0][j], f[ii][jj + (1 << (j - 1))][0][j - 1]);
			}
	
	for (int i = 1; i <= log[n]; i++)//处理竖着一根线的
		for (int ii = 1; ii <= n; ii++)
			for (int jj = 1; jj <= m; jj++) {
    
    
				f[ii][jj][i][0] = f[ii][jj][i - 1][0];
				if (ii + (1 << (i - 1)) <= n) f[ii][jj][i][0] = max(f[ii][jj][i][0], f[ii + (1 << (i - 1))][jj][i - 1][0]);
			}
		
	for (int i = 1; i <= log[n]; i++)//ST 表的合并(前面两个其实也是,但是是为了处理掉特殊情况)
		for (int j = 1; j <= log[m]; j++)
			for (int ii = 1; ii <= n; ii++)
				for (int jj = 1; jj <= m; jj++) {
    
    
					f[ii][jj][i][j] = f[ii][jj][i - 1][j - 1];
					if (ii + (1 << (i - 1)) <= n) {
    
    
						f[ii][jj][i][j] = max(f[ii][jj][i][j], f[ii + (1 << (i - 1))][jj][i - 1][j - 1]);
						if (jj + (1 << (j - 1)) <= m) {
    
    
							f[ii][jj][i][j] = max(f[ii][jj][i][j], max(f[ii][jj + (1 << (j - 1))][i - 1][j - 1], f[ii + (1 << (i - 1))][jj + (1 << (j - 1))][i - 1][j - 1]));
						}
					}
					else if (jj + (1 << (j - 1)) <= m) f[ii][jj][i][j] = max(f[ii][jj][i][j], f[ii][jj + (1 << (j - 1))][i - 1][j - 1]);
				}
	
	while (k--) {
    
    
		scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
		int logx = log[x2 - x1 + 1];
		int logy = log[y2 - y1 + 1];//询问
		printf("%d\n", max(max(f[x1][y1][logx][logy], f[x1][y2 - (1 << logy) + 1][logx][logy]), max(f[x2 - (1 << logx) + 1][y1][logx][logy], f[x2 - (1 << logx) + 1][y2 - (1 << logy) + 1][logx][logy])));
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43346722/article/details/115048079