Submission #480113

# Submission time Handle Problem Language Result Execution time Memory
480113 2021-10-14T16:50:23 Z ocarima 3D Histogram (COCI20_histogram) C++14
0 / 110
1 ms 332 KB
#include<bits/stdc++.h>

using namespace std;

#define fastio ios_base::sync_with_stdio(false); cin.tie(NULL)
#define lli long long int
#define vi vector<int>
#define vlli vector<long long int>
#define pii pair<int, int>
#define plli pair<lli, lli>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define repa(i, a, b) for(int i = (a); i >= (b); i--)
#define repv(x, v) for(auto x : v)
#define debug(x) cout << #x << " = " << x << endl
#define debugsl(x) cout << #x << " = " << x << ", "
#define debugarr(x, a, b) cout << #x << " = ["; rep(i, a, b) cout << x[i] << ", "; cout << "]\n"
#define pb push_back
#define nl "\n"

#define MAXN 200003
#define MAXLG 19

lli n, a[MAXN], b[MAXN], ga[MAXN], gb[MAXN], pot[MAXLG], res;

lli encuentraOptimo(lli li, lli ri, lli ld, lli rd){

    if (li > ri) return 0;

    lli mitad = (li + ri) / 2;
    lli tmp, ans;
    lli opt, posopt;

    // ITERA POR TODO EN RANGO BUSCANDO LA VENTANA ÓPTIMA PARA ESA MITAD
    opt = 0;
    rep(pos, ld, rd){
        tmp = min(ga[mitad], ga[pos]) * min(gb[mitad], gb[pos]) * (pos - mitad + 1);
        if (tmp >= opt){
            opt = tmp;
            posopt = pos;
        }
    }

    // UNA VEZ CON EL ÓPTIMO, REVISA AMBAS MITADES USANDO EL ÓPTIMO COMO LIMITE
    ans = max(opt, encuentraOptimo(li, mitad - 1, ld, min(rd, posopt)));
    ans = max(ans, encuentraOptimo(mitad + 1, ri, max(ld, posopt), rd));

    return ans;
}

lli divide_y_venceras(lli l, lli r){
    // MANEJA LOS RANGOS TRIVIALES (ANCHO <= 1)
    if (l > r) return 0;
    if (l == r) return a[l] * b[l];

    lli ans = 0;
    lli mitad = (l + r) / 2;

    lli tmp;

    // LA REGLA DE ORO DEL DIVIDE Y VENCERAS:
    // 1. La solución está enteramente en el lado izquierdo.
    // 2. La solución está enteramente en el lado derecho.
    // 3. La solución contiene a la mitad del rango.

    // 1. y 2. VE LO MEJOR DEL LADO IZQUIERDO Y LO MEJOR DEL LADO DERECHO.
    ans = max(divide_y_venceras(l, mitad - 1), divide_y_venceras(mitad + 1, r));

    // 3. ES NECESARIO PROBAR TODAS LAS OPCIONES QUE CONTIENEN A LA MITAD DEL RANGO.

    // NINGUN RANGO PUEDE TENER UN a O UN b MAYOR QUE LOS DE LA MITAD,
    // CONSTRUYE EL ARREGLO DE MÍNIMOS A PARTIR DE LA MITAD DEL RANGO HACIA LA IZQUIERDA Y LA DERECHA.
    ga[mitad] = a[mitad];
    gb[mitad] = b[mitad];
    rep(i, mitad + 1, r){
        ga[i] = min(a[i], ga[i - 1]);
        gb[i] = min(b[i], gb[i - 1]);
    }
    repa(i, mitad - 1, l){
        ga[i] = min(a[i], ga[i + 1]);
        gb[i] = min(b[i], gb[i + 1]);
    }

    // CONSIDERA EL CASO DE QUE LA MEJOR VENTANA SEA SOLO LA MITAD.
    ans = max(ans, a[mitad] * b[mitad]);

    // ENCUENTRA EL INICIO OPTIMO HACIENDO UN DIVIDE Y VENCERAS SOBRE EL LADO IZQUIERDO.
    ans = max(ans, encuentraOptimo(l, mitad, mitad, r));

    return ans;
}

int main()
{
    fastio;
    pot[0] = 1;
    rep(p, 1, MAXLG - 1) pot[p] = pot[p - 1] * 2;

    cin >> n;
    rep(i, 1, n) cin >> a[i] >> b[i];
    res = divide_y_venceras(1, n);
    reverse(a + 1, a + 1 + n);
    reverse(b + 1, b + 1 + n);
    res = max(res, divide_y_venceras(1, n));
    cout << res << nl;
}

Compilation message

histogram.cpp: In function 'long long int divide_y_venceras(long long int, long long int)':
histogram.cpp:58:9: warning: unused variable 'tmp' [-Wunused-variable]
   58 |     lli tmp;
      |         ^~~
histogram.cpp: In function 'long long int encuentraOptimo(long long int, long long int, long long int, long long int)':
histogram.cpp:31:14: warning: 'posopt' may be used uninitialized in this function [-Wmaybe-uninitialized]
   31 |     lli opt, posopt;
      |              ^~~~~~
# Verdict Execution time Memory Grader output
1 Incorrect 1 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 1 ms 332 KB Output isn't correct
2 Halted 0 ms 0 KB -