Cod sursa(job #2614945)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 12 mai 2020 22:08:08
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.68 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int NMAX = 1e5 + 5, ROOT = 1;

int N, Q;

vector < int > G[NMAX];

int W[NMAX], Max_Son[NMAX];

int M = 1;
int Chain[NMAX], Level[NMAX], First[NMAX], Pos[NMAX], Size[NMAX], father[NMAX];

int A[NMAX];

int *T[NMAX];

inline void Initialize (int Id, int N)
{
    int Needed = (N << 2);
    T[Id] = new int [Needed + 1];

    for(int i = 1; i <= Needed; ++i)
        T[Id][i] = 0;

    return;
}

inline void Update (int Id, int Node, int a, int b, int pos, int Val)
{
    if(a == b)
    {
        T[Id][Node] = Val;

        return;
    }

    int Mid = (a + b) >> 1;

    if(pos <= Mid)
        Update(Id, 2 * Node, a, Mid, pos, Val);

    if(pos > Mid)
        Update(Id, 2 * Node + 1, Mid + 1, b, pos, Val);

    T[Id][Node] = max(T[Id][2 * Node], T[Id][2 * Node + 1]);

    return;
}

inline int Query (int Id, int Node, int a, int b, int qa, int qb)
{
    if(qa <= a && b <= qb)
        return T[Id][Node];

    int Mid = (a + b) >> 1;
    int p_Left = 0, p_Right = 0;

    if(qa <= Mid)
        p_Left = Query(Id, 2 * Node, a, Mid, qa, qb);

    if(qb > Mid)
        p_Right = Query(Id, 2 * Node + 1, Mid + 1, b, qa, qb);

    return max(p_Left, p_Right);
}

static inline void Read ()
{
    f.tie(nullptr);

    f >> N >> Q;

    for(int i = 1; i <= N; ++i)
        f >> A[i];

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

        G[a].push_back(b);
        G[b].push_back(a);
    }

    return;
}

static inline void DFS_1 (int Node, int From, int Lvl)
{
    W[Node] = 1;
    Max_Son[Node] = -1;

    Level[Node] = Lvl;

    father[Node] = From;

    for(auto it : G[Node])
        if(it != From)
        {
            DFS_1(it, Node, Lvl + 1);

            W[Node] += W[it];

            if(Max_Son[Node] == -1 || (Max_Son[Node] != -1 && W[it] > W[Max_Son[Node]]))
                Max_Son[Node] = it;
        }

    return;
}

static inline void DFS_2 (int Node, int From)
{
    Chain[Node] = M;
    Pos[Node] = (++Size[M]);

    if(Pos[Node] == 1)
        First[M] = Node;

    if(Max_Son[Node] == -1)
        return;

    DFS_2(Max_Son[Node], Node);

    for(auto it : G[Node])
        if(it == Max_Son[Node] || it == From)
            continue;
        else
        {
            ++M;

            DFS_2(it, Node);
        }

    return;
}

static inline void Precalculation ()
{
    DFS_1(ROOT, 0, 1);
    DFS_2(ROOT, 0);

    for(int i = 1; i <= M; ++i)
        Initialize(i, Size[i]);

    for(int i = 1; i <= N; ++i)
        Update(Chain[i], 1, 1, Size[Chain[i]], Pos[i], A[i]);

    return;
}

static inline void Update (int X, int Val)
{
    Update(Chain[X], 1, 1, Size[Chain[X]], Pos[X], Val);

    return;
}

static inline int Query (int X, int Y)
{
    if(Chain[X] == Chain[Y])
        return Query(Chain[X], 1, 1, Size[Chain[X]], min(Pos[X], Pos[Y]), max(Pos[X], Pos[Y]));

    if(Level[First[Chain[X]]] > Level[First[Chain[Y]]])
        swap(X, Y);

    return max(Query(Y, First[Chain[Y]]), Query(father[First[Chain[Y]]], X));
}

static inline void TestCase ()
{
    int Type = 0;
    f >> Type;

    if(Type == 0)
    {
        int X = 0, Val = 0;
        f >> X >> Val;

        Update(X, Val);

        return;
    }

    int X = 0, Y = 0;
    f >> X >> Y;

    g << Query(X, Y) << '\n';

    return;
}

static inline void Solve ()
{
    while(Q--)
        TestCase();

    return;
}

int main()
{
    Read();

    Precalculation();

    Solve();

    return 0;
}