Cod sursa(job #2673894)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 18 noiembrie 2020 09:26:53
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.02 kb
#include <fstream>
#include <vector>

using namespace std;

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

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

int N, Q, A[NMAX];

vector < int > G[NMAX];

///
int M = 0;

int father[NMAX], W[NMAX], Max_Son[NMAX];
int chain[NMAX], pos[NMAX];

int how_many[NMAX];

int First[NMAX], Level[NMAX];
///

static inline int my_min (int a, int b)
{
    return ((a < b) ? a : b);
}

static inline int my_max (int a, int b)
{
    return ((a > b) ? a : b);
}

static inline void my_swap (int &x, int &y)
{
    x = (x ^ y), y = (x ^ y), x = (x ^ y);

    return;
}

class SegmentTree
{
    int *V;

public:
    inline void Initialize (int N)
    {
        V = new int [((N << 2) + 1)];

        for(int i = 1; i <= (N << 2); ++i)
            V[i] = 0;

        return;
    }

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

            return;
        }

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

        if(pos <= Mid)
            Update((Node << 1), a, Mid, pos, Val);

        if(pos > Mid)
            Update(((Node << 1) + 1), Mid + 1, b, pos, Val);

        V[Node] = my_max(V[(Node << 1)], V[((Node << 1) + 1)]);

        return;
    }

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

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

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

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

        return my_max(p_Left, p_Right);
    }
} AINT[NMAX];

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 X = 0, Y = 0;
        f >> X >> Y;

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

    return;
}

static inline void DFS (int Node, int from = -1, int lvl = 1)
{
    father[Node] = from;

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

    Level[Node] = lvl;

    for(auto it : G[Node])
        if(it != from)
        {
            DFS(it, Node, lvl + 1);

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

            W[Node] += W[it];
        }

    return;
}

static inline void Go (int Node, int from = -1)
{
    chain[Node] = M;
    pos[Node] = ++how_many[M];

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

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

    Go(Max_Son[Node], Node);

    for(auto it : G[Node])
        if(it != from && it != Max_Son[Node])
            ++M, Go(it, Node);

    return;
}

static inline void Initialize ()
{
    for(int i = 1; i <= M; ++i)
        AINT[i].Initialize(how_many[i]);

    for(int i = 1; i <= N; ++i)
        AINT[chain[i]].Update(1, 1, how_many[chain[i]], pos[i], A[i]);

    return;
}

static inline void Precalculation ()
{
    DFS(ROOT);

    M = 1, Go(ROOT);

    Initialize();

    return;
}

static inline int Query (int X, int Y)
{
    if(chain[X] == chain[Y])
        return AINT[chain[X]].Query(1, 1, how_many[chain[X]], my_min(pos[X], pos[Y]), my_max(pos[X], pos[Y]));

    if(Level[First[chain[X]]] > Level[First[chain[Y]]])
        my_swap(X, Y);

    int p_1 = Query(Y, First[chain[Y]]);
    int p_2 = Query(father[First[chain[Y]]], X);

    return my_max(p_1, p_2);
}

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

    if(Type == 0)
    {
        AINT[chain[X]].Update(1, 1, how_many[chain[X]], pos[X], Y);

        return;
    }

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

    return;
}

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

    return;
}

int main()
{
    Read();

    Precalculation();

    Solve();

    return 0;
}