Cod sursa(job #3191459)

Utilizator SSKMFSS KMF SSKMF Data 9 ianuarie 2024 18:58:41
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.64 kb
#include <fstream>
#include <vector>
using namespace std;

ifstream cin ("heavypath.in");
ofstream cout ("heavypath.out");

class AINT {
    private:
        AINT *urmatorul[2] = { };
        int lungime = 0 , maxim = 0;
        void insert (const int stanga , const int dreapta , const int pozitie , const int valoare)
        {
            if (stanga == dreapta)
                { maxim = valoare; return; }

            const int mijloc = (stanga + dreapta) >> 1;
            if (pozitie <= mijloc)
            {
                if (urmatorul[0] == NULL)
                    { urmatorul[0] = new AINT; }

                urmatorul[0] -> insert(stanga , mijloc , pozitie , valoare);
                maxim = max(maxim , urmatorul[0] -> maxim);
                return;
            }
        
            if (urmatorul[1] == NULL)
                { urmatorul[1] = new AINT; }

            urmatorul[1] -> insert(mijloc + 1 , dreapta , pozitie , valoare);
            maxim = max(maxim , urmatorul[1] -> maxim);
        }
        int query (const int stanga , const int dreapta , const int stanga_interval , const int dreapta_interval)
        {
            if (stanga_interval <= stanga && dreapta <= dreapta_interval)
                { return maxim; }

            const int mijloc = (stanga + dreapta) >> 1;
            if (dreapta_interval <= mijloc) { return (urmatorul[0] == NULL ? 0 : urmatorul[0] -> query(stanga , mijloc , stanga_interval , dreapta_interval)); }
            if (stanga_interval > mijloc) { return (urmatorul[1] == NULL ? 0 : urmatorul[1] -> query(mijloc + 1 , dreapta , stanga_interval , dreapta_interval)); }
            return max((urmatorul[0] == NULL ? 0 : urmatorul[0] -> query(stanga , mijloc , stanga_interval , dreapta_interval)) , (urmatorul[1] == NULL ? 0 : urmatorul[1] -> query(mijloc + 1 , dreapta , stanga_interval , dreapta_interval)));
        }
    public:
        void push_back (const int valoare) { (*this).insert(1 , 100000 , ++lungime , valoare); }
        void update (const int pozitie , const int valoare) { (*this).insert(1 , 100000 , pozitie , valoare); }
        int query (const int stanga , const int dreapta) { return (*this).query(1 , 100000 , stanga , dreapta); }
        int size () { return lungime; }

        void Parcurgere (const int stanga , const int dreapta)
        {
            if (stanga == dreapta)
                { cout << maxim << ' '; }

            const int mijloc = (stanga + dreapta) >> 1;
            if (urmatorul[0]) { urmatorul[0] -> Parcurgere(stanga , mijloc); }
            if (urmatorul[1]) { urmatorul[1] -> Parcurgere(mijloc + 1 , dreapta); }
        }
} *candidati[100001];

vector <int> adiacenta[100001];
int valoare[100001] , lant[100001] , pozitie_lant[100001] , urmatorul[100001] , adancime[100001];

void Descompunere (const int nod_actual , const int nod_sursa)
{
    adancime[nod_actual] = adancime[nod_sursa] + 1;

    if (adiacenta[nod_actual].size() == 1 && nod_sursa)
    {
        lant[nod_actual] = ++lant[0];
        candidati[lant[nod_actual]] = new AINT;
        candidati[lant[nod_actual]] -> push_back(valoare[nod_actual]);
        urmatorul[lant[nod_actual]] = nod_sursa;
        pozitie_lant[nod_actual] = 1;
        return;
    }

    int legat = 0;
    for (auto nod_vecin : adiacenta[nod_actual]) {
        if (nod_vecin != nod_sursa)
        {
            Descompunere(nod_vecin , nod_actual);

            if (candidati[lant[nod_vecin]] -> size() > candidati[lant[legat]] -> size())
                { legat = nod_vecin; }
        }
    }

    lant[nod_actual] = lant[legat];
    candidati[lant[legat]] -> push_back(valoare[nod_actual]);
    pozitie_lant[nod_actual] = candidati[lant[legat]] -> size();
    urmatorul[lant[nod_actual]] = nod_sursa;
}

int main ()
{
    int numar_noduri , numar_operatii;
    cin >> numar_noduri >> numar_operatii;

    for (int indice = 1 ; indice <= numar_noduri ; indice++)
        { cin >> valoare[indice]; }

    for (int indice = 1 , nod[2] ; indice < numar_noduri ; indice++) 
        { cin >> nod[0] >> nod[1]; adiacenta[nod[0]].push_back(nod[1]); adiacenta[nod[1]].push_back(nod[0]); }

    Descompunere(1 , 0);

    while (numar_operatii--)
    {
        uint16_t tip;
        cin >> tip;
        
        switch (tip)
        {
            case 0: { int nod , valoare; cin >> nod >> valoare; candidati[lant[nod]] -> update(pozitie_lant[nod] , valoare); } 
                break;

            case 1:
            {
                int nod_1 , nod_2;
                cin >> nod_1 >> nod_2;

                int maxim = 0;
                while (true)
                {
                    if (lant[nod_1] == lant[nod_2]) {
                        maxim = max(maxim , candidati[lant[nod_1]] -> query(min(pozitie_lant[nod_1] , pozitie_lant[nod_2]) , max(pozitie_lant[nod_1] , pozitie_lant[nod_2])));
                        break;
                    }

                    if (adancime[urmatorul[lant[nod_1]]] > adancime[urmatorul[lant[nod_2]]])
                    {
                        maxim = max(maxim , candidati[lant[nod_1]] -> query(pozitie_lant[nod_1] , candidati[lant[nod_1]] -> size()));
                        nod_1 = urmatorul[lant[nod_1]];
                        continue;
                    }
                    
                    maxim = max(maxim , candidati[lant[nod_2]] -> query(pozitie_lant[nod_2] , candidati[lant[nod_2]] -> size()));
                    nod_2 = urmatorul[lant[nod_2]];
                }

                cout << maxim << '\n';
            }
            break;
        }
    }

    cout.close(); cin.close();
    return 0;
}