Cod sursa(job #2427850)

Utilizator Alex_BubBuburuzan Alexandru Alex_Bub Data 2 iunie 2019 14:26:09
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

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

const int NMax = 1e5;

int N, M, K, Val[NMax + 5], W[NMax + 5], Ci[NMax + 5], Cj[NMax + 5], L[NMax + 5], Lev[NMax + 5], A[20][NMax + 5], TT[NMax + 5];
vector <int> G[NMax + 5], AIT[NMax + 5];

void DFS(int Nod, int Tata)
{
    W[Nod] = 1, Lev[Nod] = Lev[Tata] + 1, A[0][Nod] = Tata;

    for(auto Vecin : G[Nod])
        if(Vecin != Tata)
            DFS(Vecin, Nod), W[Nod] += W[Vecin];
}

void MakePath(int Nod, int Tata, int c)
{
    Ci[Nod] = c, Cj[Nod] = ++L[c];

    int maxi = -1, x = 0;

    for(auto Vecin : G[Nod])
    {
        if(Vecin != Tata && W[Vecin] > maxi)
            maxi = W[Vecin], x = Vecin;
    }
    if(x) MakePath(x, Nod, c);

    for(auto Vecin : G[Nod])
        if(Vecin != Tata && Vecin != x)
        {
            TT[++K] = Nod;
            MakePath(Vecin, Nod, K);
        }
}

int Stramos(int Nod, int P)
{
    int k = 0;

    while(P)
    {
        if(P & 1) Nod = A[k][Nod];
        P >>= 1, k++;
    }
    return Nod;
}

int LCA(int x, int y)
{
    if(Lev[x] < Lev[y]) swap(x, y);
    x = Stramos(x, Lev[x] - Lev[y]);

    if(x == y) return x;

    for(int i = log2(Lev[x]); i >= 0; i--)
    {
        if(A[i][x] != A[i][y])
            x = A[i][x], y = A[i][y];
    }
    return A[0][x];
}

void Update(int d, int i, int st, int dr, int p, int val)
{
    if(p < st || dr < p) return;

    if(st == dr)
    {
        AIT[d][i] = val;
        return;
    }
    int m = (st + dr) / 2;

    Update(d, 2 * i, st, m, p, val);
    Update(d, 2 * i + 1, m + 1, dr, p, val);

    AIT[d][i] = max(AIT[d][2 * i], AIT[d][2 * i + 1]);
}

int Querry(int d, int i, int st, int dr, int a, int b)
{
    if(b < st || dr < a) return 0;

    if(a <= st && dr <= b)
        return AIT[d][i];

    int m = (st + dr) >> 1;

    return max(Querry(d, 2 * i, st, m, a, b), Querry(d, 2 * i + 1, m + 1, dr, a, b));
}

int Solve(int x, int y)
{
    int Sol = 0;

    while(Ci[x] != Ci[y])
    {
        Sol = max(Sol, Querry(Ci[x], 1, 1, L[Ci[x]], 1, Cj[x]));
        x = TT[Ci[x]];
    }
    return max(Sol, Querry(Ci[x], 1, 1, L[Ci[x]], Cj[y], Cj[x]));
}

void Precalc()
{
    for(int i = 1; (1 << i) <= N; i++)
        for(int j = 1; j <= N; j++)
            A[i][j] = A[i - 1][A[i - 1][j]];

    for(int i = 1; i <= K; i++)
        for(int j = 1; j <= 4 * L[i]; j++)
            AIT[i].push_back(0);

    for(int i = 1; i <= N; i++)
        Update(Ci[i], 1, 1, L[Ci[i]], Cj[i], Val[i]);
}

int main()
{
    fin >> N >> M;

    for(int i = 1; i <= N; i++)
        fin >> Val[i];

    for(int i = 1, a, b; i < N; i++)
    {
        fin >> a >> b;

        G[a].push_back(b);
        G[b].push_back(a);
    }
    DFS(1, 0); MakePath(1, 0, ++K); Precalc();

    while(M--)
    {
        int p, x, y; fin >> p >> x >> y;

        if(p == 0)
            Update(Ci[x], 1, 1, L[Ci[x]], Cj[x], y);
        else
        {
            int c = LCA(x, y);
            fout << max(Solve(x, c), Solve(y, c)) << '\n';
        }
    }
    fin.close();
    fout.close();

    return 0;
}