行列の最大値
トピックリンク: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;
}