Cod sursa(job #2837128)

Utilizator andreiomd1Onut Andrei andreiomd1 Data 21 ianuarie 2022 20:05:04
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.97 kb
#include <fstream>
#include <vector>

using namespace std;

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

const int NMAX = 1e5 + 1;
const int ROOT = 1;
const int INF = 1e9;

int N, v[NMAX], Q;

vector < int > G[NMAX];

int father[NMAX], w[NMAX], level[NMAX], Max_Son[NMAX];
int cnt = 1, Chain[NMAX], pos[NMAX], Size[NMAX], First[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);
}

class SegmentTree
{
    int *A;

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

        for(int i = 1; i <= Size; ++i)
            A[i] = -INF;

        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 = -INF, p_Right = -INF;

        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 Add_Edge (int x, int y)
{
    G[x].push_back(y), G[y].push_back(x);

    return;
}

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

    f >> N >> Q;

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

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

        Add_Edge(u, v);
    }

    return;
}

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

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

            w[Node] += w[it];

            if(Max_Son[Node] == -1 || (w[it] > w[Max_Son[Node]]))
                Max_Son[Node] = it;
        }

    return;
}

static inline void Go (int Node, int from = 0)
{
    Chain[Node] = cnt, pos[Node] = ++Size[cnt];

    if(Size[cnt] == 1)
        First[cnt] = Node;

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

    Go(Max_Son[Node], Node);

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

    return;
}

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

    Go(ROOT);

    for(int i = 1; i <= cnt; ++i)
        AINT[i].Initialize(Size[i]);

    for(int i = 1; i <= N; ++i)
        AINT[Chain[i]].Update(1, 1, Size[Chain[i]], pos[i], v[i]);

    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(Chain[x] == Chain[y])
        return AINT[Chain[x]].Query(1, 1, Size[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);

    return my_max(Query(y, First[Chain[y]]), Query(father[First[Chain[y]]], x));
}

static inline void TestCase ()
{
    short int _type = 0;
    int x = 0, y = 0;

    f >> _type >> x >> y;

    if(_type == 0)
    {
        AINT[Chain[x]].Update(1, 1, Size[Chain[x]], pos[x], y);

        return;
    }

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

    return;
}

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

    return;
}

int main()
{
    Read();

    Decomposition();

    Solve();

    return 0;
}