【Ybt高効率アドバンスト4-3-4】行列最大値

行列の最大値

トピックリンク:ybt高効率アドバンスト4-3-4

一般的なアイデア

あなたに行列を与え、複数回尋ね、部分行列の最大値を尋ねます。

アイデア

この質問は、2次元のSTテーブルを使用して確認できます。

考えるのは簡単ですが、実装は非常に嫌なものと言えます。

クエリは実際には問題ありません。主な理由は、合併の考え方が明確でなければならないということです。
そして、あなたは行列なので、1行の2つのケースをマージする必要があります。(横線と縦線)
あなたはマトリックスなので、この2つを扱わないと、その後の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