Cod sursa(job #2765227)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 25 iulie 2021 20:54:47
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.05 kb
#include <fstream>
#include <vector>

using namespace std;

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

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

int N, Val[NMAX];
vector < int > G[NMAX];

int Level[NMAX], father[NMAX], Size[NMAX], Max_Son[NMAX];
int Id[NMAX], Pos[NMAX];

int chains = 1, cnt[NMAX], Top[NMAX];

int Q;

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);
}

class SegmentTree
{
    int *A;

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

        for(int i = 1; i <= (Elems << 2); ++i)
            A[i] = 0;

        return;
    }

    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((Node << 1), a, Mid, pos, Val);

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

        A[Node] = my_max(A[(Node << 1)], A[((Node << 1) + 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((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);
    }
} *Chains;

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

    f >> N >> Q;

    for(int i = 1; i <= N; ++i)
        f >> Val[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 = 0)
{
    Level[Node] = lvl, father[Node] = from, Size[Node] = 1;

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

            if(Size[it] > Size[Max_Son[Node]])
                Max_Son[Node] = it;
        }

    return;
}

static inline void Go (int Node, int from = -1)
{
    ++cnt[chains];

    if(cnt[chains] == 1)
        Top[chains] = Node;

    Id[Node] = chains, Pos[Node] = cnt[chains];

    if(Size[Node] == 1)
        return;

    Go(Max_Son[Node], Node);

    for(auto it : G[Node])
        if(it == from || it == Max_Son[Node])
            continue;
        else ++chains, Go(it, Node);

    return;
}

static inline void Load_Values ()
{
    for(int i = 1; i <= N; ++i)
        Chains[Id[i]].Update(1, 1, cnt[Id[i]], Pos[i], Val[i]);

    return;
}

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

    Go(ROOT);

    Chains = new SegmentTree [(chains + 1)];

    for(int i = 1; i <= chains; ++i)
        Chains[i].Initialize(cnt[i]);

    Load_Values();

    return;
}

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

    return;
}

static inline int Query (int X, int Y)
{
    if(Id[X] == Id[Y])
        return Chains[Id[X]].Query(1, 1, cnt[Id[X]], my_min(Pos[X], Pos[Y]), my_max(Pos[X], Pos[Y]));

    if(Level[Top[Id[X]]] > Level[Top[Id[Y]]])
        my_swap(X, Y);

    return my_max(Query(Y, Top[Id[Y]]), Query(father[Top[Id[Y]]], X));
}

static inline void TestCase ()
{
    int t = 0, x = 0, y = 0;
    f >> t >> x >> y;

    if(t == 0)
    {
        Val[x] = y;

        Chains[Id[x]].Update(1, 1, cnt[Id[x]], Pos[x], Val[x]);

        return;
    }

    if(x == y)
    {
        g << Val[x] << '\n';

        return;
    }

    g << Query(x, y) << '\n';

    return;
}

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

    return;
}

int main()
{
    Load_Graph();

    Heavy_Light_Decomposition();

    Solve();

    return 0;
}