Título
Dê um n ∗ mn * mn∗retângulo m , cada grade tem uma cor. Existem 4 cores no total.
Um cubo legal é composto do quarto superior esquerdo como cor 1, o quarto superior direito como cor 2, o quarto inferior esquerdo como cor 3 e o quarto inferior direito como cor 4.
QQConsultas Q , cada submatriz de consulta(x 1, y 1, x 2, y 2) (x1, y1, x2, y2)( x 1 ,y 1 ,x 2 ,A área do maior cubo legal em y 2 ) . Se não existir, imprima 0.
n, m ≤ 500, q ≤ 3 e 5 n, m \ le 500, q \ le 3e5n ,m≤5 0 0 ,q≤3 e 5
Ideias para resolução de problemas
Primeiro, para cada ponto, encontre o tamanho máximo do cubo legal que pode ser obtido tomando este ponto como o canto inferior direito da parte superior esquerda do quadrado legal. Complexidade O (nmlog (n)) O (nmlog (n))O ( n m l o g ( n ) )
Então, a cada consulta, a resposta é dividida em duas. Ao verificar, descubra se o valor máximo no retângulo correspondente é maior ou igual ao valor de verificação. Use RMQ bidimensional para ir paraO (1) O (1)O ( 1 ) consulta, complexidade de pré-processamentoO (nm ∗ log (nm)) O (nm * log (nm))O ( n m∗l o g ( n m ) )
Complexidade totalO (nm ∗ log (nm) + q ∗ log (n)) O (nm * log (nm) + q * log (n))O ( n m∗l o g ( n m )+q∗l o g ( n ) )
#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define lowbit(x) ((x)&(-(x)))
#define mid ((l+r)>>1)
#define lson rt<<1, l, mid
#define rson rt<<1|1, mid+1, r
#define fors(i, a, b) for(int i = (a); i < (b); ++i)
using namespace std;
int n, m, Q;
const int maxn = 520;
char s[maxn];
int d[4][maxn][maxn];
int a[maxn][maxn];
bool in(int x, int y){
if(x < 1 || x > n || y < 1 || y > m) return false; return true;}
bool block(int x1, int y1, int x2, int y2, int o){
if(!in(x1, y1) || !in(x2, y2)) return false;
int sum = (x2-x1+1)*(y2-y1+1);
return sum == d[o][x2][y2]-d[o][x1-1][y2]-d[o][x2][y1-1]+d[o][x1-1][y1-1];
}
bool check(int x, int y, int r){
int x1 = x-r+1, y1 = y-r+1, x2, y2;
if(!block(x1, y1, x, y, 0)) return false;
y1 += r; y2 = y+r; x2 = x;
if(!block(x1, y1, x2, y2, 1)) return false;
x1 += r; x2 += r;
if(!block(x1, y1, x2, y2, 3)) return false;
y1 -= r; y2 -= r;
if(!block(x1, y1, x2, y2, 2)) return false;
return true;
}
int lg2[maxn];
int dp[9][9][maxn][maxn];
int get_max(int x1, int y1, int x2, int y2){
int k = lg2[x2-x1+1], l = lg2[y2-y1+1];
int t1 = max(dp[k][l][x1][y1], dp[k][l][x2-(1<<k)+1][y1]);
int t2 = max(dp[k][l][x1][y2-(1<<l)+1], dp[k][l][x2-(1<<k)+1][y2-(1<<l)+1]);
return max(t1, t2);
}
bool check(int x1, int y1, int x2, int y2, int lim){
if(x1 > x2 || y1 > y2) return false;
return get_max(x1, y1, x2, y2) >= lim;
}
int main()
{
lg2[0] = -1;
fors(i, 1, maxn) lg2[i] = lg2[i>>1]+1;
cin>>n>>m>>Q;
fors(i, 1, n+1) {
scanf("%s", s+1);
fors(j , 1, m+1)
if(s[j] == 'G') d[1][i][j] = 1;
else if(s[j] == 'Y') d[2][i][j] = 1;
else if(s[j] == 'R') d[0][i][j] = 1;
else if(s[j] == 'B') d[3][i][j] = 1;
}
fors(o, 0, 4)
fors(i, 1, n+1)
fors(j, 1, m+1)
d[o][i][j] += d[o][i][j-1]+d[o][i-1][j]-d[o][i-1][j-1];
fors(i, 1, n+1) fors(j, 1, m+1){
int l = 1, r = n;
while(l <= r){
if(check(i, j, mid)) a[i][j] = mid, l = mid+1;
else r = mid-1;
}
}
fors(k, 0, 9)
fors(l, 0, 9)
fors(i, 1, n+1)
fors(j, 1, m+1){
if(k == 0 && l == 0) {
dp[k][l][i][j] = a[i][j]; continue;}
else if(l == 0) {
if(i+(1<<(k-1)) <= n)
dp[k][l][i][j] = max(dp[k-1][l][i][j], dp[k-1][l][i+(1<<(k-1))][j]);
else dp[k][l][i][j] = dp[k-1][l][i][j];
}
else {
if(j+(1<<(l-1)) <= m)
dp[k][l][i][j] = max(dp[k][l-1][i][j], dp[k][l-1][i][j+(1<<(l-1))]);
else dp[k][l][i][j] = dp[k][l-1][i][j];
}
}
while(Q--){
int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
int l = 1, r = n;
int ans = 0;
while(l <= r){
if(check(x1+mid-1, y1+mid-1, x2-mid, y2-mid, mid)) ans = mid, l = mid+1;
else r = mid-1;
}
printf("%d\n", 4*ans*ans);
}
}