Cod sursa(job #3227874)

Utilizator SSKMFSS KMF SSKMF Data 3 mai 2024 12:45:55
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.32 kb
#include <fstream>
#include <vector>
using namespace std;

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

vector <int> adiacenta[100001];
int valoare[100001] , invers[100001] , nod_sursa[100001] , reprezentant[100001] , lant[100001] , pozitie[100001] , cantitate[100002] , adancime[100001] , adaos[100001] , arbore[400000];

void Parcurgere (const int nod_actual)
{
    int maxim = 0;
    cantitate[nod_actual] = 1;
    adancime[nod_actual] = adancime[nod_sursa[nod_actual]] + 1;
    for (auto nod_vecin : adiacenta[nod_actual]) {
        if (nod_vecin != nod_sursa[nod_actual])
        {
            nod_sursa[nod_vecin] = nod_actual;
            Parcurgere(nod_vecin);

            cantitate[nod_actual] += cantitate[nod_vecin];
            if (cantitate[nod_vecin] > cantitate[maxim])
                { maxim = nod_vecin; }
        }
    }

    if (!maxim)
    {
        lant[nod_actual] = ++lant[0];
        reprezentant[lant[nod_actual]] = nod_actual;
        pozitie[nod_actual] = 1;
        return;
    }

    lant[nod_actual] = lant[maxim];
    pozitie[nod_actual] = pozitie[maxim] + 1;
    reprezentant[lant[nod_actual]] = nod_actual;
}

int Build (const int nod , const int stanga , const int dreapta , const int termen)
{
    if (stanga == dreapta)
        { arbore[nod + termen] = valoare[invers[stanga]]; return nod + termen; }

    int candidat = 0;
    const int mijloc = (stanga + dreapta) >> 1;
    candidat = max(candidat , Build(nod << 1 , stanga , mijloc , termen));
    candidat = max(candidat , Build((nod << 1) | 1 , mijloc + 1 , dreapta , termen));
    arbore[nod + termen] = max(arbore[(nod << 1) + termen] , arbore[((nod << 1) | 1) + termen]);
    return candidat;
}

void Update (const int nod , const int stanga , const int dreapta , const int pozitie , const int termen)
{
    if (stanga == dreapta)
        { cin >> arbore[nod + termen]; return; }

    const int mijloc = (stanga + dreapta) >> 1;
    if (pozitie <= mijloc) { Update(nod << 1 , stanga , mijloc , pozitie , termen); }
    else { Update((nod << 1) | 1 , mijloc + 1 , dreapta , pozitie , termen); }

    arbore[nod + termen] = max(arbore[(nod << 1) + termen] , arbore[((nod << 1) | 1) + termen]);
}

int Query (const int nod , const int stanga , const int dreapta , const int stanga_interval , const int dreapta_interval , const int termen)
{
    if (stanga_interval <= stanga && dreapta <= dreapta_interval)
        { return arbore[nod + termen]; }

    int raspuns = 0;
    const int mijloc = (stanga + dreapta) >> 1;
    if (stanga_interval <= mijloc) { raspuns = max(raspuns , Query(nod << 1 , stanga , mijloc , stanga_interval , dreapta_interval , termen)); }
    if (dreapta_interval > mijloc) { raspuns = max(raspuns , Query((nod << 1) | 1 , mijloc + 1 , dreapta , stanga_interval , dreapta_interval , termen)); }
    return raspuns;
}

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]); }

    Parcurgere(1);

    for (int indice = 1 ; indice <= numar_noduri ; indice++)
        { cantitate[indice] = 0; }

    for (int indice = 1 ; indice <= numar_noduri ; indice++)
        { cantitate[lant[indice] + 1]++; }

    for (int indice = 2 ; indice <= lant[0] + 1 ; indice++)
        { cantitate[indice] += cantitate[indice - 1]; }

    for (int indice = 1 ; indice <= numar_noduri ; indice++)
        { invers[pozitie[indice] += cantitate[lant[indice]]] = indice; }

    for (int indice = 1 ; indice <= lant[0] ; indice++)
        { adaos[indice + 1] = Build(1 , cantitate[indice] , cantitate[indice + 1] , adaos[indice]); }

    while (numar_operatii--)
    {
        int8_t tip;
        cin >> tip;

        if (tip == '0')
        {
            int nod;
            cin >> nod;
            Update(1 , cantitate[lant[nod]] , cantitate[lant[nod] + 1] , pozitie[nod] , adaos[lant[nod]]);
        }
        else
        {
            int nod_1 , nod_2;
            cin >> nod_1 >> nod_2;

            int raspuns = 0;
            while (lant[nod_1] != lant[nod_2]) {
                if (adancime[reprezentant[lant[nod_1]]] > adancime[reprezentant[lant[nod_2]]])
                {
                    raspuns = max(raspuns , Query(1 , cantitate[lant[nod_1]] , cantitate[lant[nod_1] + 1] , pozitie[nod_1] , pozitie[reprezentant[lant[nod_1]]] , adaos[lant[nod_1]]));
                    nod_1 = nod_sursa[reprezentant[lant[nod_1]]];
                }
                else
                {
                    raspuns = max(raspuns , Query(1 , cantitate[lant[nod_2]] , cantitate[lant[nod_2] + 1] , pozitie[nod_2] , pozitie[reprezentant[lant[nod_2]]] , adaos[lant[nod_2]]));
                    nod_2 = nod_sursa[reprezentant[lant[nod_2]]];
                }
            }

            raspuns = max(raspuns , Query(1 , cantitate[lant[nod_1]] , cantitate[lant[nod_1] + 1] , min(pozitie[nod_1] , pozitie[nod_2]) , max(pozitie[nod_1] , pozitie[nod_2]) , adaos[lant[nod_1]]));

            cout << raspuns << '\n';
        }
    }

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