Cod sursa(job #1929648)

Utilizator Burbon13Burbon13 Burbon13 Data 17 martie 2017 21:29:21
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.08 kb
#include <bits/stdc++.h>

using namespace std;

const int nmx = 100002;

int n,m;
vector <int> g[nmx],aux;
vector <vector<int> > lant,arb;
int tata_lant[nmx];
int greutate[nmx],val[nmx],care_lant[nmx],poz_lant[nmx],nivel[nmx];

void citire()
{
    scanf("%d %d", &n, &m);

    for(int i = 1; i <= n; ++i)
        scanf("%d", &val[i]);

    int nod1,nod2;
    for(int i = 1; i < n; ++i)
    {
        scanf("%d %d", &nod1, &nod2);
        g[nod1].push_back(nod2);
        g[nod2].push_back(nod1);
    }
}

void dfs(int nod, int tata)
{
    int maxim = -1, urm_nod = -1;

    greutate[nod] = 1;
    nivel[nod] = nivel[tata] + 1;
    for(vector<int>::iterator it = g[nod].begin(); it != g[nod].end(); ++it)
        if(*it != tata)
        {
            dfs(*it,nod);
            greutate[nod] += greutate[*it];
            if(greutate[*it] > maxim)
            {
                maxim = greutate[*it];
                urm_nod = *it;
            }
            tata_lant[care_lant[*it]] = nod;
        }

    if(maxim == -1)
    {
        aux.clear();
        aux.push_back(nod);
        lant.push_back(aux);
        care_lant[nod] = lant.size()-1;
    }
    else
    {
        lant[care_lant[urm_nod]].push_back(nod);
        care_lant[nod] = care_lant[urm_nod];
    }
}

void aranjare_lanturi()
{
    for(size_t i = 0; i < lant.size(); ++i)
        reverse(lant[i].begin(),lant[i].end());
}

int int_st, int_dr, nr_lant, val_schimb, pozitie, max_cautat;

void update(int st, int dr, int nod)
{
    if(st == dr)
    {
        arb[nr_lant][nod] = val_schimb;
        return;
    }

    int mij = (st + dr) / 2;

    if(pozitie <= mij)
        update(st,mij,2*nod);
    else
        update(mij+1,dr,2*nod+1);

    arb[nr_lant][nod] = max(arb[nr_lant][2*nod],arb[nr_lant][2*nod+1]);
}

void query(int st, int dr, int nod)
{
    if(int_st <= st && int_dr >= dr)
    {
        max_cautat = max(max_cautat,arb[nr_lant][nod]);
        return;
    }

    int mij = (st + dr) / 2;

    if(int_st <= mij)
        query(st,mij,2*nod);
    if(int_dr > mij)
        query(mij+1,dr,2*nod+1);
}

void arbori_intervale()
{
    for(size_t i = 0; i < lant.size(); ++i)
    {
        arb.push_back(aux);
        arb[i].resize(lant[i].size() * 4 + 2,0);

        nr_lant = i;
        for(size_t j = 0; j < lant[i].size(); ++j)
        {
            poz_lant[lant[i][j]] = j + 1;
            val_schimb = val[lant[i][j]];
            pozitie = poz_lant[lant[i][j]];
            update(1,lant[i].size(),1);
        }
    }
}

void cautare(int nod1, int nod2)
{
    max_cautat = -1;
    while(care_lant[nod1] != care_lant[nod2])
    {
        if(nivel[nod1] < nivel[nod2])
        {
            int_st = 1;
            int_dr = poz_lant[nod2];
            nr_lant = care_lant[nod2];
            query(1,lant[care_lant[nod2]].size(),1);
            nod2 = tata_lant[care_lant[nod2]];
        }
        else
        {
            int_st = 1;
            int_dr = poz_lant[nod1];
            nr_lant = care_lant[nod1];
            query(1,lant[care_lant[nod1]].size(),1);
            nod1 = tata_lant[care_lant[nod1]];
        }
    }

    int_st = min(poz_lant[nod1],poz_lant[nod2]);
    int_dr = max(poz_lant[nod1],poz_lant[nod2]);
    nr_lant = care_lant[nod1];
    query(1,lant[care_lant[nod1]].size(),1);
}

void operatii()
{
    int op,x,y;
    for(int i = 1; i <= m; ++i)
    {
        scanf("%d %d %d", &op, &x, &y);
        if(op == 0)
        {
            pozitie = poz_lant[x];
            val_schimb = y;
            nr_lant = care_lant[x];
            update(1,lant[nr_lant].size(),1);
        }
        else
        {
            cautare(x,y);
            printf("%d\n", max_cautat);
        }
    }
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    citire();
    dfs(1,0);
    tata_lant[care_lant[1]] = 0;
    aranjare_lanturi();
    arbori_intervale();
    //for(int i = 0; i < 4; ++i)
    //  printf("%d ", tata_lant[i]);
    operatii();
    return 0;
}