Cod sursa(job #1689623)

Utilizator BugirosRobert Bugiros Data 14 aprilie 2016 13:45:02
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.92 kb
#include <fstream>
#include <vector>
using namespace std;

const int MAXN = 100005;

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

vector<int> vecini[MAXN];
int v[MAXN];
int nivel[MAXN];
int n;

struct arborelant
{
    vector<int> vallant;
    void actualizare(int nod, int st, int dr, int poz, int val)
    {
        if (st == dr)
        {
            vallant[nod] = val;
            return;
        }
        int mij = (st + dr) / 2;
        if (poz <= mij)
            actualizare(2 * nod, st, mij, poz, val);
        else actualizare(2 * nod + 1, mij + 1, dr, poz, val);
        vallant[nod] = max(vallant[2 * nod], vallant[2 * nod + 1]);
    }
    int interogare(int nod, int st, int dr, int x, int y)
    {
        if (st == x && dr == y)
            return vallant[nod];
        int mij = (st + dr) / 2;
        if (y <= mij)
            return interogare(2 * nod, st, mij, x, y);
        if (x > mij)
            return interogare(2 * nod + 1, mij + 1, dr, x, y);
        return max(interogare(2 * nod, st, mij, x, mij),
                   interogare(2 * nod + 1, mij + 1, dr, mij + 1, y));
    }
};

void citire(int &m)
{
    in >> n >> m;
    for (int i = 1;i <= n;++i)
        in >> v[i];
    for (int i = 1;i < n;++i)
    {
        int x,y;
        in >> x >> y;
        vecini[x].push_back(y);
        vecini[y].push_back(x);
    }
}

int nrsubarbore[MAXN];

int nrlanturi;
vector<int> lant[MAXN];
int idlant[MAXN];
int pozlant[MAXN];
int tatalant[MAXN];

void dfs(int nod, int tata)
{
    int fiu_cu_subarbore_maxim = 0;
    nrsubarbore[nod] = 1;
    for (unsigned int i = 0;i < vecini[nod].size();++i)
    {
        int vecin = vecini[nod][i];
        if (vecin == tata)
            continue;
        nivel[vecin] = nivel[nod] + 1;
        dfs(vecin, nod);
        nrsubarbore[nod] += nrsubarbore[vecin];
        if(nrsubarbore[vecin] > nrsubarbore[fiu_cu_subarbore_maxim])
            fiu_cu_subarbore_maxim = vecin;
    }

    if (fiu_cu_subarbore_maxim == 0)//frunza
    {
        ++nrlanturi;
        idlant[nod] = nrlanturi;
        lant[nrlanturi].push_back(nod);
        pozlant[nod] = 1;
        return;
    }

    idlant[nod] = idlant[fiu_cu_subarbore_maxim];
    pozlant[nod] = pozlant[fiu_cu_subarbore_maxim] + 1;
    lant[idlant[nod]].push_back(nod);

    for (unsigned int i = 0;i < vecini[nod].size();++i)
    {
        int vecin = vecini[nod][i];
        if(vecin == tata || vecin == fiu_cu_subarbore_maxim)
            continue;
        tatalant[idlant[vecin]] = nod;
    }
}

arborelant alant[MAXN];

void construire_arbori()
{
    for (int i = 1;i <= nrlanturi;++i)
    {
        int llant = lant[i].size();
        alant[i].vallant.resize(4 * llant + 2);
        for (int j = 0;j < llant;++j)
            alant[i].actualizare(1, 1, llant, j + 1, v[lant[i][j]]);
    }
}

int main()
{
    int m;
    citire(m);
    //construire lanturi
    nivel[1] = 1;
    dfs(1,0);

    construire_arbori();

    while(m > 0)
    {
        int t,x,y;
        in >> t >> x >> y;
        if (t == 0)//actualizare
            alant[idlant[x]].actualizare(1, 1, lant[idlant[x]].size(), pozlant[x], y);
        else//interogare
        {
            int rasp = -1;
            while(idlant[x] != idlant[y])
            {
                if(nivel[tatalant[idlant[x]]] < nivel[tatalant[idlant[y]]])
                    swap(x,y);
                int nr = alant[idlant[x]].interogare(1, 1, lant[idlant[x]].size(), pozlant[x], lant[idlant[x]].size());
                if (nr > rasp)
                    rasp = nr;
                x = tatalant[idlant[x]];
            }
            int nr = alant[idlant[x]].interogare(1, 1, lant[idlant[x]].size(), min(pozlant[x], pozlant[y]), max(pozlant[x], pozlant[y]));
            if (nr > rasp)
                rasp = nr;
            out << rasp << '\n';
        }
        --m;
    }
    return 0;
}