Sari la conținut

Autor: Ștefan-Cosmin Dăscălescu

Soluția problemei Cuburi (OJI 2002, clasa a VI-a)#

Cunoștințe necesare

Link problemă

Această problemă poate fi accesată aici.

Pentru primele două cerințe, vom afla frecvența maximă a unei valori din șir, precum și care sunt valorile care au acea frecvență maximă.

Pentru cea de-a treia cerință, putem precalcula doi vectori, \(st\) și \(dr\), cu semnificația că \(st[i]\) reprezintă numărul maxim de poziții consecutive cu valoare egală care conțin poziția \(i\) de la stânga, iar \(dr[i]\) este definit în mod similar, dar pentru o secvență care începe la poziția \(i\) și se extinde la dreapta.

Pentru fiecare poziție \(i\), acum ce putem face este să verificăm dacă pozițiile \(i-1\) și \(i+1\) au valori egale pentru a verifica dacă putem pune laolaltă șirurile de cuburi, iar maximul dintre lungimile verificate va fi răspunsul final al problemei.

Mai jos puteți găsi o soluție neoficială care ia punctajul maxim.

#include <fstream>
#include <iostream>

using namespace std;
ifstream fin("cuburi.in");
ofstream fout("cuburi.out");

int f[11];
int v[200002], st[200002], dr[200002], mst[200002], mdr[200002];

int main() {
    int n, x;
    fin >> n;
    int fmax = 0;
    int nrculori = 0;

    for (int i = 1; i <= n; i++) {
        fin >> x;
        v[i] = x;
        if (f[x] == 0)  // daca culoarea x e intalnita prima data
            nrculori++; // cresc numarul de culori
        f[x]++;
        if (f[x] > fmax)
            fmax = f[x];
    }
    fout << nrculori << '\n';
    for (int i = 1; i <= 10; i++) {
        if (f[i] == fmax)
            fout << i << " ";
    }
    fout << '\n';
    /// cer 3
    for (int i = 1; i <= n; i++) {
        if (v[i] == v[i - 1])
            st[i] = st[i - 1] + 1;
        else
            st[i] = 1;
        mst[i] = max(mst[i - 1], st[i]);
    }

    for (int i = n; i >= 1; i--) {
        if (v[i] == v[i + 1])
            dr[i] = dr[i + 1] + 1;
        else
            dr[i] = 1;
        mdr[i] = max(mdr[i + 1], dr[i]);
    }
    // lung maxima
    int p[200002], j = 0; // in p retinem pozitiile de unde pot scoate cuburi pt a obtine lmax
    int lmax = -1, l;
    for (int i = 1; i <= n; i++) {
        if (v[i - 1] == v[i + 1])      // daca prin taiere alipesc doua siruri cu aceleasi elemente
            l = st[i - 1] + dr[i + 1]; // lungimea rezultata e nr de elem egale de la stanga, resp de la dr
        else
            l = 0;
        l = max(l, max(mst[i - 1], mdr[i + 1]));
        if (l > lmax) { // daca am obtinut o lungime mai mare , memorez poz elem de taiat, prima in vect p
            lmax = l;
            j = 0;
            p[j++] = i;
        } 
        else {
            if (l == lmax) { // daca am obtinut aceeasi lungime , adaugam la lungimea existenta
                p[j++] = i;
            }
        }
    }

    for (int i = 0; i < j; i++)
        fout << p[i] << " ";
    return 0;
}