Codeforces 1301E-Nanosoft (RMQ bidimensional + dos puntos)

Título

Dar un n ∗ mn * mnortem rectángulo, cada cuadrícula tiene un color. Hay 4 colores en total.
Un cubo legal está compuesto por el cuarto superior izquierdo como color 1, el cuarto superior derecho como color 2, el cuarto inferior izquierdo como color 3 y el cuarto inferior derecho como color 4.
QQQ consultas, cada submatriz de consulta(x 1, y 1, x 2, y 2) (x1, y1, x2, y2)( x 1 ,y 1 ,x 2 ,El área del cubo legal más grande en y 2 ) . Si no existe, salida 0.
n, m ≤ 500, q ≤ 3 e 5 n, m \ le 500, q \ le 3e5n ,metro5 0 0 ,q3 y 5

Ideas para resolver problemas

Primero, para cada punto, encuentre el tamaño máximo de cubo legal que se puede obtener tomando este punto como la esquina inferior derecha de la parte superior izquierda del cuadrado legal. Complejidad O (nmlog (n)) O (nmlog (n))O ( n m l o g ( n ) )
Luego, en cada consulta, la respuesta se divide en dos. Al verificar, encuentre si el valor máximo en el rectángulo correspondiente es mayor o igual que el valor de verificación. Utilice RMQ bidimensional para ir aO (1) O (1)O ( 1 ) consulta, complejidad de preprocesamientoO (nm ∗ log (nm)) O (nm * log (nm))O ( n ml o g ( n m ) )
Complejidad totalO (nm ∗ log (nm) + q ∗ log (n)) O (nm * log (nm) + q * log (n))O ( n ml o g ( n m )+ql 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);
    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_43202683/article/details/104319057
Recomendado
Clasificación