首先考虑长和宽相等的情况。
看到要选出的子长方体的规模是 a×a×ba×a×b ,
可以考虑先预处理出对于每个 (i,j,k)(i,j,k) ,在第 kk 层内,以 为右下角的最大的全 N 正方形的边长 s(i,j,k)s(i,j,k) 。这个可以用悬线法 O(pqr)O(pqr) 预处理出。
然后枚举 1≤i≤p,1≤j≤q1≤i≤p,1≤j≤q ,并设选出的子长方体的 xx 坐标右边界为 , yy 坐标右边界为 。
这时候,如果 zz 坐标的范围是 ,那么在这样的限制下最大的 4ab4ab 为:
4(y−x+1)mink=xys(i,j,k)4(y−x+1)mink=xys(i,j,k)
于是问题简化为:给出一个长度为 rr 的序列,求一个区间,最大化 的值。
先利用单调栈,预处理出序列的每个元素 kk 的 和 suf[k]suf[k] :
pre[k]pre[k] : kk 往左第一个满足 的 hh ,没有则为 。
suf[k]suf[k] : kk 往右第一个满足 的 hh ,没有则为 。
这样,对于一个 kk ,所有满足 的区间 [x,y][x,y] 的最小值都等于 s(i,j,k)s(i,j,k) 。
那么上面这些 [x,y][x,y] 中,最长的区间长度显然为 [pre[k]+1,suf[k]−1][pre[k]+1,suf[k]−1] 。
于是用 4×s(i,j,k)×(suf[k]−pre[k]−1)4×s(i,j,k)×(suf[k]−pre[k]−1) 更新答案。
长和高相等,宽和高相等同样处理。
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Rof(i, a, b) for (i = a; i >= b; i--)
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
inline char get() {
char c; while ((c = getchar()) != 'P' && c != 'N'); return c;
}
const int N = 155;
int p, q, r, le[N][N][N], up[N][N][N], oz[N][N][N], s1[N][N][N],
s2[N][N][N], s3[N][N][N], ans, pre[N], top, stk[N];
bool a[N][N][N];
int main() {
int i, j, k; p = read(); q = read(); r = read();
char c; For (j, 1, q) For (i, 1, p) For (k, 1, r)
c = get(), a[i][j][k] = c == 'N';
For (i, 1, p) For (j, 1, q) For (k, 1, r) {
le[i][j][k] = a[i][j][k] ? le[i - 1][j][k] + 1 : 0;
up[i][j][k] = a[i][j][k] ? up[i][j - 1][k] + 1 : 0;
oz[i][j][k] = a[i][j][k] ? oz[i][j][k - 1] + 1 : 0;
s1[i][j][k] = min(min(le[i][j][k], up[i][j][k]), s1[i - 1][j - 1][k] + 1);
s2[i][j][k] = min(min(le[i][j][k], oz[i][j][k]), s2[i - 1][j][k - 1] + 1);
s3[i][j][k] = min(min(up[i][j][k], oz[i][j][k]), s3[i][j - 1][k - 1] + 1);
}
For (i, 1, p) For (j, 1, q) {
stk[top = 0] = 0; For (k, 1, r) {
while (top && s1[i][j][stk[top]] >= s1[i][j][k]) top--;
pre[stk[++top] = k] = stk[top - 1];
}
stk[top = 0] = r + 1; Rof (k, r, 1) {
while (top && s1[i][j][stk[top]] >= s1[i][j][k]) top--;
stk[++top] = k; ans = max(ans, s1[i][j][k]
* (stk[top - 1] - pre[k] - 1));
}
}
For (i, 1, p) For (k, 1, r) {
stk[top = 0] = 0; For (j, 1, q) {
while (top && s2[i][stk[top]][k] >= s2[i][j][k]) top--;
pre[stk[++top] = j] = stk[top - 1];
}
stk[top = 0] = q + 1; Rof (j, q, 1) {
while (top && s2[i][stk[top]][k] >= s2[i][j][k]) top--;
stk[++top] = j; ans = max(ans, s2[i][j][k]
* (stk[top - 1] - pre[j] - 1));
}
}
For (j, 1, q) For (k, 1, r) {
stk[top = 0] = 0; For (i, 1, p) {
while (top && s3[stk[top]][j][k] >= s3[i][j][k]) top--;
pre[stk[++top] = i] = stk[top - 1];
}
stk[top = 0] = p + 1; Rof (i, p, 1) {
while (top && s3[stk[top]][j][k] >= s3[i][j][k]) top--;
stk[++top] = i; ans = max(ans, s3[i][j][k]
* (stk[top - 1] - pre[i] - 1));
}
}
cout << ans * 4 << endl; return 0;
}