Cod sursa(job #2442915)

Utilizator Alex_BubBuburuzan Alexandru Alex_Bub Data 25 iulie 2019 19:12:53
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.65 kb
#include <fstream>
#include <vector>
#include <cmath>

using namespace std;

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

const int NMax = 1e5, BufferSize = 1e5;

char B[BufferSize + 5];

int N, M, K, Val[NMax + 5], W[NMax + 5], F[NMax + 5], P[NMax + 5], L[NMax + 5], Lev[NMax + 5], A[20][NMax + 5], TT[NMax + 5], AIT[4 * NMax + 5], Nr, pos;
vector <int> G[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];
}

int Parse() {
    int Value = 0;

    while(B[pos] < '0' || B[pos] > '9') {
        pos++;
        if(pos == BufferSize) {
            fread(B, BufferSize, 1, stdin);
            pos = 0;
        }
    }

    while(B[pos] >= '0' && B[pos] <= '9') {
        Value = Value * 10 + (B[pos] - '0');

        pos++;
        if(pos == BufferSize) {
            fread(B, BufferSize, 1, stdin);
            pos = 0;
        }
    }
    return Value;
}

void MakePath(int Nod, int Tata, int c)
{
    L[Nod] = c, P[Nod] = ++Nr;
    if(F[c] == 0) F[c] = Nr;

    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 i, int st, int dr, int p, int val)
{
    if(p < st || dr < p) return;

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

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

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

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

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

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

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

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

    while(L[x] != L[y])
    {
        Sol = max(Sol, Querry(1, 1, N, F[L[x]], P[x]));
        x = TT[L[x]];
    }
    return max(Sol, Querry(1, 1, N, P[y], P[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 <= N; i++)
        Update(1, 1, N, P[i], Val[i]);
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    fread(B, BufferSize, 1, stdin);

    N = Parse(), M = Parse();

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

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

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

    while(M--)
    {
        int p = Parse(), x = Parse(), y = Parse();

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

    return 0;
}