Cod sursa(job #2765292)

Utilizator AlexandruabcdeDobleaga Alexandru Alexandruabcde Data 26 iulie 2021 11:01:23
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.37 kb
#include <bits/stdc++.h>

using namespace std;

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

constexpr int NMAX = 1e5 + 5;

int N, M;
int val[NMAX];
vector <int> G[NMAX];
int Size[NMAX];
int Id[NMAX];
int Size_Id[NMAX];
int First[NMAX];
int Max_Son[NMAX];
int Dad[NMAX];
int Level[NMAX];

struct Aint
{
    int *A;

    Aint(int size) : A(new int[4 * size])
    {

    }

    void Update_Tree (int nod, int a, int b, int poz, int val) {
        if (a == b) {
            A[nod] = val;
            return;
        }

        int mij = (a + b) / 2;
        if (poz <= mij) Update_Tree(2*nod, a, mij, poz, val);
        if (mij < poz) Update_Tree(2*nod+1, mij+1, b, poz, val);
        A[nod] = max(A[2*nod], A[2*nod+1]);
    }

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

        int mij = (a + b) / 2;
        int Rez_1 = 0, Rez_2 = 0;

        if (qa <= mij) Rez_1 = Query(2*nod, a, mij, qa, qb);
        if (mij < qb) Rez_2 = Query(2*nod+1, mij+1, b, qa, qb);

        return max(Rez_1, Rez_2);
    }
};

vector <Aint*> Arbore;

void Dfs (int Node, int dad = -1, int lvl = 0) {
    Level[Node] = lvl;
    Size[Node] = 1;
    Dad[Node] = dad;
    for (auto it : G[Node]) {
        if (it == dad) continue;

        Dfs(it, Node, lvl+1);
        Size[Node] += Size[it];

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

int chains = 1;
void Split (int Node, int dad = -1) {
    Id[Node] = chains;
    Size_Id[chains]++;

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

    Split(Max_Son[Node], Node);

    for (auto it : G[Node]) {
        if (it == dad || it == Max_Son[Node])
            continue;

        ++ chains;
        First[chains] = it;
        Split(it, Node);
    }
}

void Read () {
    f >> N >> M;

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

    for (int i = 1; i < N; ++ i ) {
        int x, y;
        f >> x >> y;

        G[x].push_back(y);
        G[y].push_back(x);
    }
}

int Query (int X, int Y) {
    if (Id[X] == Id[Y]) {
        ///Acelasi lant

        int st = min(Level[X] - Level[First[Id[X]]] + 1, Level[Y] - Level[First[Id[X]]] + 1);
        int dr = max(Level[X] - Level[First[Id[X]]] + 1, Level[Y] - Level[First[Id[X]]] + 1);
        return Arbore[Id[X]]->Query(1, 1, Size_Id[Id[X]], st, dr);
    }

    if (Level[First[Id[X]]] < Level[First[Id[Y]]])
        swap(X, Y);

    int ans = Arbore[Id[X]]->Query(1, 1, Size_Id[Id[X]], 1, Level[X] - Level[First[Id[X]]] + 1);
    return max(ans, Query(Dad[First[Id[X]]], Y));
}

void Init_Arbore () {
    Arbore.push_back(new Aint(0));
    for (int i = 1; i <= chains; ++ i )
        Arbore.push_back(new Aint(Size_Id[i]));

    for (int i = 1; i <= N; ++ i )
        Arbore[Id[i]]->Update_Tree(1, 1, Size_Id[Id[i]], Level[i] - Level[First[Id[i]]] + 1, val[i]);
}

void Solve () {
    for (; M; -- M ) {
        int tip, x, y;

        f >> tip >> x >> y;

        if (tip == 0)
            Arbore[Id[x]]->Update_Tree(1, 1, Size_Id[Id[x]], Level[x] - Level[First[Id[x]]] + 1, y);
        else {
            g << Query(x, y) << '\n';
        }
    }
}

int main () {
    Read();
    Dfs(1);
    First[1] = 1;
    Split(1);

    Init_Arbore ();
    Solve();

    return 0;
}