Cod sursa(job #2923626)

Utilizator Razvan48Capatina Razvan Nicolae Razvan48 Data 16 septembrie 2022 21:45:46
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 7.49 kb
#include <fstream>
#include <vector>

using namespace std;

const int NMAX = 100000;
const int LOGMAX = 17;

int v[1 + NMAX];
vector<int> graf[1 + NMAX];

bool vizitatCostJos[1 + NMAX];
int costJos[1 + NMAX];

bool vizitatLanturi[1 + NMAX];
vector<vector<int>> lanturi;

int indexLantNod[1 + NMAX];
int pozLantNod[1 + NMAX];

vector<vector<int>> arboriLanturi;
pair<int, int> tataLant[1 + NMAX];

bool vizitatLCA[1 + NMAX];
vector<int> liniarizareLCA;
int primaAparitieLCA[1 + NMAX];
int adancimeNod[1 + NMAX];
int log2[1 + 2 * NMAX];
pair<int, int> rmq[1 + 2 * NMAX][1 + LOGMAX];

void dfsCostJos(int nod)
{
    vizitatCostJos[nod] = true;
    costJos[nod] = 1;

    for (int i = 0; i < graf[nod].size(); i++)
    {
        int fiu = graf[nod][i];

        if (!vizitatCostJos[fiu])
        {
            dfsCostJos(fiu);
            costJos[nod] = max(costJos[nod], costJos[fiu] + 1);
        }
    }
}

void dfsLCA(int nod)
{
    vizitatLCA[nod] = true;
    liniarizareLCA.push_back(nod);
    primaAparitieLCA[nod] = (int)liniarizareLCA.size() - 1;

    adancimeNod[nod] = 1;

    for (int i = 0; i < graf[nod].size(); i++)
    {
        int fiu = graf[nod][i];

        if (!vizitatLCA[fiu])
        {
            dfsLCA(fiu);
            liniarizareLCA.push_back(nod);

            adancimeNod[nod] = max(adancimeNod[nod], adancimeNod[fiu] + 1);
        }
    }
}

void dfsLanturi(int nod)
{
    vizitatLanturi[nod] = true;
    lanturi.back().push_back(nod);

    int indexLantCurent = (int)lanturi.size() - 1;
    int pozLantCurent = (int)lanturi.back().size() - 1;

    int nodBunJos = -1;
    int costNodBunJos = -1;

    for (int i = 0; i < graf[nod].size(); i++)
    {
        int fiu = graf[nod][i];

        if (!vizitatLanturi[fiu])
        {
            if (costJos[fiu] > costNodBunJos)
            {
                nodBunJos = fiu;
                costNodBunJos = costJos[fiu];
            }
        }
    }

    if (nodBunJos != -1)
        dfsLanturi(nodBunJos);

    for (int i = 0; i < graf[nod].size(); i++)
    {
        int fiu = graf[nod][i];

        if (!vizitatLanturi[fiu] && fiu != nodBunJos)
        {
            lanturi.emplace_back();
            lanturi.back().push_back(0);

            tataLant[(int)lanturi.size() - 1].first = indexLantCurent;
            tataLant[(int)lanturi.size() - 1].second = pozLantCurent;

            dfsLanturi(fiu);
        }
    }
}

void buildAint(int indexLanturi, int index, int st, int dr)
{
    if (st == dr)
    {
        arboriLanturi[indexLanturi][index] = v[lanturi[indexLanturi][st]];
        return;
    }

    int mij = (st + dr) / 2;
    int fiuSt = 2 * index;
    int fiuDr = 2 * index + 1;

    buildAint(indexLanturi, fiuSt, st, mij);
    buildAint(indexLanturi, fiuDr, mij + 1, dr);

    arboriLanturi[indexLanturi][index] = max(arboriLanturi[indexLanturi][fiuSt], arboriLanturi[indexLanturi][fiuDr]);
}

void updateAint(int indexLanturi, int index, int st, int dr, int poz, int val)
{
    if (st == dr)
    {
        arboriLanturi[indexLanturi][index] = val;
        return;
    }

    int mij = (st + dr) / 2;
    int fiuSt = 2 * index;
    int fiuDr = 2 * index + 1;

    if (poz <= mij)
        updateAint(indexLanturi, fiuSt, st, mij, poz, val);
    else
        updateAint(indexLanturi, fiuDr, mij + 1, dr, poz, val);

    arboriLanturi[indexLanturi][index] = max(arboriLanturi[indexLanturi][fiuSt], arboriLanturi[indexLanturi][fiuDr]);
}

int queryAint(int indexLanturi, int index, int st, int dr, int stQ, int drQ)
{
    if (st == stQ && drQ == dr)
    {
        return arboriLanturi[indexLanturi][index];
    }

    int mij = (st + dr) / 2;
    int fiuSt = 2 * index;
    int fiuDr = 2 * index + 1;

    if (drQ <= mij)
        return queryAint(indexLanturi, fiuSt, st, mij, stQ, drQ);
    else if (stQ >= mij + 1)
        return queryAint(indexLanturi, fiuDr, mij + 1, dr, stQ, drQ);
    else
        return max(queryAint(indexLanturi, fiuSt, st, mij, stQ, mij), queryAint(indexLanturi, fiuDr, mij + 1, dr, mij + 1, drQ));
}

void preCalcRMQ()
{
    for (int i = 2; i < liniarizareLCA.size(); i++)
        log2[i] = log2[i / 2] + 1;

    for (int i = 1; i < liniarizareLCA.size(); i++)
    {
        rmq[i][0].first = adancimeNod[liniarizareLCA[i]];
        rmq[i][0].second = liniarizareLCA[i];
    }

    for (int l = 1; (1 << l) < liniarizareLCA.size(); l++)
    {
        for (int i = 1; i + (1 << l) - 1 < liniarizareLCA.size(); i++)
        {
            if (rmq[i][l - 1].first > rmq[i + (1 << (l - 1))][l - 1].first)
            {
                rmq[i][l].first = rmq[i][l - 1].first;
                rmq[i][l].second = rmq[i][l - 1].second;
            }
            else
            {
                rmq[i][l].first = rmq[i + (1 << (l - 1))][l - 1].first;
                rmq[i][l].second = rmq[i + (1 << (l - 1))][l - 1].second;
            }
        }
    }
}

int calcLCA(int x, int y)
{
    if (primaAparitieLCA[x] > primaAparitieLCA[y])
        swap(x, y);

    int st = primaAparitieLCA[x];
    int dr = primaAparitieLCA[y];
    int logaritm2 = log2[dr - st + 1];

    if (rmq[st][logaritm2].first > rmq[dr - (1 << logaritm2) + 1][logaritm2].first)
        return rmq[st][logaritm2].second;
    else
        return rmq[dr - (1 << logaritm2) + 1][logaritm2].second;
}

int calcSol(int jos, int sus)
{
    int sol = -1;

    while (jos != sus)
    {
        if (indexLantNod[jos] == indexLantNod[sus])
        {
            sol = max(sol, queryAint(indexLantNod[jos], 1, 1, (int)lanturi[indexLantNod[jos]].size() - 1, pozLantNod[sus], pozLantNod[jos]));
            jos = sus;
        }
        else
        {
            sol = max(sol, queryAint(indexLantNod[jos], 1, 1, (int)lanturi[indexLantNod[jos]].size() - 1, 1, pozLantNod[jos]));
            jos = lanturi[tataLant[indexLantNod[jos]].first][tataLant[indexLantNod[jos]].second];
        }
    }

    return sol;
}

int main()
{
    ifstream in("heavypath.in");
    ofstream out("heavypath.out");

    int n, m;
    in >> n >> m;

    for (int i = 1; i <= n; i++)
        in >> v[i];

    for (int i = 1; i <= n - 1; i++)
    {
        int a, b;
        in >> a >> b;

        graf[a].push_back(b);
        graf[b].push_back(a);
    }

    dfsCostJos(1);

    lanturi.emplace_back();
    lanturi.emplace_back();
    lanturi.back().push_back(0);

    tataLant[0].first = -1;
    tataLant[0].second = -1;
    tataLant[1].first = -1;
    tataLant[1].second = -1;

    dfsLanturi(1);
    for (int i = 1; i < lanturi.size(); i++)
    {
        for (int j = 1; j < lanturi[i].size(); j++)
        {
            indexLantNod[lanturi[i][j]] = i;
            pozLantNod[lanturi[i][j]] = j;
        }
    }

    arboriLanturi.resize(lanturi.size());
    for (int i = 1; i < lanturi.size(); i++)
        arboriLanturi[i].resize(4 * (int)lanturi[i].size());
    for (int i = 1; i < lanturi.size(); i++)
        buildAint(i, 1, 1, (int)lanturi[i].size() - 1);

    liniarizareLCA.push_back(0);
    dfsLCA(1);
    preCalcRMQ();

    for (int i = 1; i <= m; i++)
    {
        int t, x, y;
        in >> t >> x >> y;

        if (t == 0)
            updateAint(indexLantNod[x], 1, 1, (int)lanturi[indexLantNod[x]].size() - 1, pozLantNod[x], y);
        else
        {
            int stramos = calcLCA(x, y);

            out << max(calcSol(x, stramos), calcSol(y, stramos)) << '\n';
        }
    }

    return 0;
}