Cod sursa(job #3296084)

Utilizator mateilucaLuca Matei Gabriel mateiluca Data 11 mai 2025 11:34:32
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.62 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
int n, m, k, maxi, ord_lant, a[100005], b[100005], subarbore[100005], lant[100005], poz[100005], niv[100005], nod[100005];
int first[100005], urmatorul_lant[100005], urmatorul_nod[100005];
int aint[525005];
bool viz[100005];
vector<int> G[100005];
void Subarbore(int x)
{
    subarbore[x] = 1;
    viz[x] = 1;
    for(int e : G[x])
        if(viz[e] == 0)
        {
            Subarbore(e);
            subarbore[x] += subarbore[e];
        }
}
void Lanturi(int x, int nivel)
{
    int i, j;
    niv[x] = nivel;
    viz[x] = 1;
    lant[x] = ord_lant;
    b[++k] = a[x];poz[x] = k;nod[poz[x]] = x;
    i = 0;j = -1;
    while(i < G[x].size() && viz[G[x][i]] == 1)
        i++;
    if(i < G[x].size()) j = i, i++;
    for( ;i < G[x].size();i++)
        if(viz[G[x][i]] == 0 && subarbore[G[x][i]] > subarbore[G[x][j]])
            j = i;
    if(j > -1)
        Lanturi(G[x][j], nivel + 1);
    for(i = 0;i < G[x].size();i++)
        if(viz[G[x][i]] == 0 && i != j)
        {
            ord_lant++;
            urmatorul_nod[ord_lant] = poz[x];
            urmatorul_lant[ord_lant] = lant[x];
            first[ord_lant] = k + 1;
            Lanturi(G[x][i], nivel + 1);
        }
}
void Creare_Arbore(int nod, int st, int dr)
{
    if(st == dr)
    {
        aint[nod] = b[st];
        return ;
    }
    int mij = (st + dr) / 2;
    Creare_Arbore(2 * nod, st, mij);
    Creare_Arbore(2 * nod + 1, mij + 1, dr);
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void Update(int nod, int st, int dr, int p, int val)
{
    if(st == dr)
    {
        aint[nod] = val;
        return ;
    }
    int mij = (st + dr) / 2;
    if(p <= mij)
        Update(2 * nod, st, mij, p, val);
    else Update(2 * nod + 1, mij + 1, dr, p, val);
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
void Query(int nod, int st, int dr, int x, int y)
{
    if(x <= st && dr <= y)
    {
        maxi = max(maxi, aint[nod]);
        return ;
    }
    int mij = (st + dr) / 2;
    if(x <= mij)
        Query(2 * nod, st, mij, x, y);
    if(mij + 1 <= y)
        Query(2 * nod + 1, mij + 1, dr, x, y);
}
int Solve(int x, int y)
{
    int pozitie_x = poz[x], pozitie_y = poz[y];
    int lant_x = lant[x], lant_y = lant[y];
    int niv_x = niv[x], niv_y = niv[y];
    maxi = 0;
    while(lant_x != lant_y)
    {
        if(pozitie_x > pozitie_y)
        {
            Query(1, 1, n, first[lant_x], pozitie_x);
            pozitie_x = urmatorul_nod[lant_x];
            lant_x = urmatorul_lant[lant_x];
            niv_x = niv[nod[pozitie_x]];
        }
        else{
            Query(1, 1, n, first[lant_y], pozitie_y);
            pozitie_y = urmatorul_nod[lant_y];
            lant_y = urmatorul_lant[lant_y];
            niv_y = niv[nod[pozitie_y]];
        }
    }
    Query(1, 1, n, min(pozitie_x, pozitie_y), max(pozitie_x, pozitie_y));
    return maxi;
}

int main()
{
    int i, j, op;
    fin >> n >> m;
    for(i = 1;i <= n;i++)
        fin >> a[i];
    for(int ind = 1;ind < n;ind++)
    {
        fin >> i >> j;
        G[i].push_back(j);
        G[j].push_back(i);
    }
    Subarbore(1);
    for(i = 1;i <= n;i++)
        viz[i] = 0;
    ord_lant = 1;first[1] = 1;urmatorul_nod[1] = 1;urmatorul_lant[1] = 1;
    Lanturi(1, 0);
    Creare_Arbore(1, 1, n);
    while(m)
    {
        fin >> op >> i >> j;
        if(op == 1)
           fout << Solve(i, j) << "\n";
        else Update(1, 1, n, poz[i], j);
        m--;
    }
    fout.close();
    return 0;
}