Cod sursa(job #1689537)

Utilizator BugirosRobert Bugiros Data 14 aprilie 2016 12:35:56
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.65 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

const int MAXN = 100005;

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

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

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

bool vizitat[MAXN];
int nivel[MAXN];
int nrsubarbore[MAXN];
int idlant[MAXN];
int nrlanturi;
vector<int> lant[MAXN];
int lanttata[MAXN];
int nivellant[MAXN];
int pozlant[MAXN];
int vallant[4 * MAXN];

void dfs(int nod)
{
    vizitat[nod] = true;
    nrsubarbore[nod] = 1;
    int fiu_cu_subarbore_maxim = -1;
    for (unsigned int i = 0;i < vecini[nod].size();++i)
    {
        int vecin = vecini[nod][i];
        if (vizitat[vecin])
            continue;
        nivel[vecin] = nivel[nod] + 1;

        dfs(vecin);

        nrsubarbore[nod] += nrsubarbore[vecin];

        if(fiu_cu_subarbore_maxim == -1)
            fiu_cu_subarbore_maxim = vecin;
        else if(nrsubarbore[vecin] > nrsubarbore[fiu_cu_subarbore_maxim])
            fiu_cu_subarbore_maxim = vecin;
    }

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

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

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

void construire(int nod, int st, int dr, int decalaj, int id)
{
    if (st == dr)
    {
        vallant[nod + decalaj] = v[ lant[id][st - 1] ];
        return;
    }
    int mij = (st + dr) / 2;
    construire(2 * nod, st, mij, decalaj, id);
    construire(2 * nod + 1, mij + 1, dr, decalaj, id);

    vallant[nod + decalaj] = max(vallant[nod * 2 + decalaj], vallant[nod * 2 + 1 + decalaj]);
}

void construire_drumuri()
{
    nivel[1] = 1;
    dfs(1);
    for (int i = 1;i <= nrlanturi;++i)
    {
        reverse(lant[i].begin(), lant[i].end());//dorim parcurgere de jos in sus
        if(i > 1)
            pozlant[i] = pozlant[i - 1] + lant[i].size() * 4;
        construire(1, 1, lant[i].size(), pozlant[i], i);
    }
}

void actualizare(int nod, int st, int dr, int poz, int val, int decalaj)
{
    if (st == dr)
    {
        vallant[nod + decalaj] = val;
        return;
    }
    int mij = (st + dr) / 2;

    if (poz <= mij)
        actualizare(2 * nod, st, mij, poz, val, decalaj);
    else actualizare(2 * nod + 1, mij + 1, dr, poz, val, decalaj);

    vallant[nod + decalaj] = max(vallant[nod * 2 + decalaj], vallant[nod * 2 + 1 + decalaj]);
}

//sti - stanga interogarii    dri - dreapta interogarii
int interogare(int nod, int st, int dr, int sti, int dri, int decalaj)
{
    if (sti <= st && dr <= dri)
        return vallant[nod + decalaj];
    int mij = (st + dr) / 2;
    int rasp = 0;
    if (sti <= mij)
    {
        int nr = interogare(2 * nod, st, mij, sti, dri, decalaj);
        if (nr > rasp)
            rasp = nr;
    }
    if (mij + 1 <= dri)
    {
        int nr = interogare(2 * nod + 1, mij + 1, dr, sti, dri, decalaj);
        if (nr > rasp)
            rasp = nr;
    }
    return rasp;
}

int interogare(int x, int y)
{
    int rasp = 0;
    while(true)
    {
        if (idlant[x] == idlant[y])
        {
            if (nivel[x] > nivel[y])
                swap(x, y);
            int nr = interogare(1, 1, lant[idlant[x]].size(), nivel[x] - nivellant[idlant[x]], nivel[y] - nivellant[idlant[y]], pozlant[idlant[x]]);
            if (nr > rasp)
                rasp = nr;
            break;
        }
        if (nivellant[idlant[x]] < nivellant[idlant[y]])
            swap(x,y);
        int nr = interogare(1, 1, lant[idlant[x]].size(), 1, nivel[x] - nivellant[idlant[x]], pozlant[idlant[x]]);
        if (nr > rasp)
            rasp = nr;
        x = lanttata[idlant[x]];
    }
    return rasp;
}

int main()
{
    int m;
    citire(m);
    construire_drumuri();
    while(m > 0)
    {
        int t,x,y;
        in >> t >> x >> y;
        if (t == 0)//actualizare
            actualizare(1, 1, lant[idlant[x]].size(), nivel[x] - nivellant[idlant[x]], y, pozlant[idlant[x]] );
        else out << interogare(x,y) << '\n';
        --m;
    }
    return 0;
}