Cod sursa(job #2485838)

Utilizator DavidLDavid Lauran DavidL Data 2 noiembrie 2019 09:45:28
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.41 kb
#include <bits/stdc++.h>
using namespace std;
ifstream fi("heavypath.in");
ofstream fo("heavypath.out");
#define cin fi
#define cout fo

const int NMAX = 1e5 + 5;
const int SQ = 1e3 + 5;

int n, q;
vector <int> G[NMAX];
int v[NMAX], p[NMAX], niv[NMAX];
int inCeLant[NMAX];
vector <int> noduriLant[NMAX];
int pozInLant[NMAX];
int cntLanturi;

int aint[SQ][4 * SQ];
int st, dr, rez, poz, val;


void bagaInLant(int nod, int lant)
{
    inCeLant[nod] = lant;
    noduriLant[lant].push_back(nod);
}

void getLant(int nod)
{
    for (auto v: G[nod])
    {
        if (v != p[nod])
        {
            p[v] = nod;
            niv[v] = niv[nod] + 1;
            getLant(v);
        }
    }

    if ((G[nod].size() == 1 && nod != 1) || (nod == 1 && n == 1)) // frunza
    {
        cntLanturi++;
        bagaInLant(nod, cntLanturi);

        return;
    }

    int maxim = 0, unde = 0;
    for (auto v: G[nod])
        if (v != p[nod] && noduriLant[inCeLant[v]].size() > maxim)
            maxim = noduriLant[inCeLant[v]].size(), unde = v;

    bagaInLant(nod, inCeLant[unde]);
}

void build(int lant, int nod, int l, int r)
{
    if (l == r)
    {
        aint[lant][nod] = v[noduriLant[lant][l]];
        return;
    }

    int mij = (l + r) / 2;

    build(lant, 2 * nod, l, mij);
    build(lant, 2 * nod + 1, mij + 1, r);

    aint[lant][nod] = max(aint[lant][2 * nod], aint[lant][2 * nod + 1]);
}

void update(int lant, int nod, int l, int r)
{
    if (l == r)
    {
        aint[lant][nod] = val;
        return;
    }

    int mij = (l + r) / 2;
    if (poz <= mij)
        update(lant, 2 * nod, l, mij);
    else
        update(lant, 2 * nod + 1, mij + 1, r);

    aint[lant][nod] = max(aint[lant][2 * nod], aint[lant][2 * nod + 1]);
}

void query(int lant, int nod, int l, int r)
{
    if (st <= l && r <= dr)
    {
        rez = max(rez, aint[lant][nod]);
        return;
    }

    int mij = (l + r) / 2;
    if (st <= mij)
        query(lant, 2 * nod, l, mij);
    if (dr > mij)
        query(lant, 2 * nod + 1, mij + 1, r);
}

int main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++)
        cin >> v[i];

    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        G[u].push_back(v);
        G[v].push_back(u);
    }

    getLant(1);

    for (int i = 1; i <= cntLanturi; i++)
        reverse(noduriLant[i].begin(), noduriLant[i].end());

    for (int i = 1; i <= cntLanturi; i++)
        for (int j = 0; j < noduriLant[i].size(); j++)
            pozInLant[noduriLant[i][j]] = j;

    for (int i = 1; i <= cntLanturi; i++)
        build(i, 1, 0, noduriLant[i].size() - 1);

    /*for (int i = 1; i <= cntLanturi; i++)
    {
        for (auto x: noduriLant[i])
            cout << x << " ";
        cout << "\n";
    }
    return 0;*/



    /*poz = pozInLant[3], val = 11;
    update(inCeLant[3], 1, 0, noduriLant[inCeLant[3]].size() - 1);

    rez = 0, st = 0, dr = noduriLant[inCeLant[3]].size() - 1;
    query(inCeLant[3], 1, 0, noduriLant[inCeLant[3]].size() - 1);
    cout << rez;

    return 0;*/


    //cout << cntLanturi;
    //return 0;


    while (q--)
    {
        int t, x, y;
        cin >> t >> x >> y;
        if (t == 0)
        {
            // update: v[x] = y
            poz = pozInLant[x], val = y;
            update(inCeLant[x], 1, 0, noduriLant[inCeLant[x]].size() - 1);
        }
        else
        {
            // query: maxim pe x...y

            // il tin pe x mai jos

            int ansQuery = -1;

            while (inCeLant[x] != inCeLant[y])
            {

                int px = noduriLant[inCeLant[x]][0], py = noduriLant[inCeLant[y]][0];


                if (niv[px] < niv[py])
                    swap(x, y), swap(px, py);

                rez = 0;
                st = 0;
                dr = pozInLant[x];
                query(inCeLant[x], 1, 0, noduriLant[inCeLant[x]].size() - 1);
                ansQuery = max(ansQuery, rez);
                x = p[px];
            }

            // sunt pe acelasi lant
            rez = 0;
            st = min(pozInLant[x], pozInLant[y]);
            dr = max(pozInLant[x], pozInLant[y]);
            query(inCeLant[y], 1, 0, noduriLant[inCeLant[y]].size() - 1);
            ansQuery = max(ansQuery, rez);

            cout << ansQuery << "\n";
        }
    }


    return 0;
}