Cod sursa(job #2615049)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 13 mai 2020 16:29:41
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4 kb
#include <iostream>
#include <cstdio>
#include <vector>

using namespace std;

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

int N, Q, A[NMAX];

vector < int > G[NMAX], Sons[NMAX];
bool Sel[NMAX];

int Level[NMAX], father[NMAX], W[NMAX], Max_Son[NMAX];

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

int sp[NMAX];

class SegmentTree
{
    static const int NMAX = 1e5 + 10;

    int A[(NMAX << 2)];

public:
    inline void Update (int Node, int a, int b, int pos, int val)
    {
        if(a == b)
        {
            A[Node] = val;

            return;
        }

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

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

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

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

        return;
    }

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

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

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

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

        return max(p_Left, p_Right);
    }
} AINT;

static inline void Read ()
{
    ios_base :: sync_with_stdio(false);
    cin.tie(nullptr);

    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);

    scanf("%d%d", &N, &Q);

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

    for(int i = 1; i < N; ++i)
    {
        int X = 0, Y = 0;
        scanf("%d%d", &X, &Y);

        G[X].push_back(Y);
        G[Y].push_back(X);
    }

    return;
}

static inline void Go (int Node, int From, int Lvl)
{
    Level[Node] = Lvl;
    father[Node] = From;

    W[Node] = 1;
    Max_Son[Node] = -1;

    Sel[Node] = 1;

    for(auto it : G[Node])
        if(!Sel[it])
        {
            Go(it, Node, Lvl + 1);

            Sons[Node].push_back(it);
            W[Node] += W[it];

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

    return;
}

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

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

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

    DFS(Max_Son[Node]);

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

            DFS(it);
        }

    return;
}

static inline void Update (int Id, int pos, int val)
{
    AINT.Update(1, 1, N, sp[Id - 1] + pos, val);

    return;
}

static inline int Query (int Id, int pos1, int pos2)
{
    return AINT.Query(1, 1, N, sp[Id - 1] + pos1, sp[Id - 1] + pos2);
}

static inline void Load ()
{
    for(int i = 1; i <= N; ++i)
        Update(Chain[i], Pos[i], A[i]);

    return;
}

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

    DFS(ROOT);

    for(int i = 1; i <= M; ++i)
        sp[i] = sp[i - 1] + Size[i];

    Load();

    return;
}

static inline int F (int X, int Y)
{
    if(Chain[X] == Chain[Y])
        return Query(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(F(Y, First[Chain[Y]]), F(father[First[Chain[Y]]], X));
}

static inline void TestCase ()
{
    int Type = 0;
    scanf("%d", &Type);

    if(Type == 0)
    {
        int Node = 0, Val = 0;
        scanf("%d%d", &Node, &Val);

        Update(Chain[Node], Pos[Node], Val);

        return;
    }

    int X = 0, Y = 0;
    scanf("%d%d", &X, &Y);

    printf("%d\n", F(X, Y));

    return;
}

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

    return;
}

int main()
{
    Read();

    Precalculation();

    Solve();

    return 0;
}