Cod sursa(job #3303628)

Utilizator paulihno15Ciumandru Paul paulihno15 Data 16 iulie 2025 17:24:22
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.68 kb
#include <bits/stdc++.h>
#define NMAX 100000

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavypath.out");

int n, q, x, y, op, ans;
int val[NMAX + 3];
vector<int> arb[NMAX + 3];
bitset<NMAX + 3> viz;

int niv[NMAX + 3], sz[NMAX + 3];
int nr_L, L[NMAX + 3], Lrad[NMAX + 3], Lniv[NMAX + 3], Ldecal[NMAX + 3];
vector<int> Lant[NMAX + 3];

int tree[NMAX * 4 + 3];

void DFS(int nod) {
    int frunza = 1, max_d = -1;
    viz[nod] = 1;
    sz[nod] = 1;

    for (int vec : arb[nod]) {
        if (viz[vec]) {
            continue;
        }
        frunza = 0;
        niv[vec] = niv[nod] + 1;

        DFS(vec);
        sz[nod] += sz[vec];
        if (max_d == -1 || sz[max_d] < sz[vec]) {
            max_d = vec;
        }
    }

    if (frunza) {
        nr_L++;
        L[nod] = nr_L;
        Lant[L[nod]].push_back(nod);
    }
    else {
        L[nod] = L[max_d];
        Lant[L[nod]].push_back(nod);

        for (int vec : arb[nod]) {
            if (vec == max_d || niv[vec] < niv[nod]) {
                continue;
            }
            Lrad[L[vec]] = nod;
            Lniv[L[vec]] = niv[nod];
        }
    }
}

void build_tree(int st, int dr, int node, int decal, int poz_l) {
    if (st == dr) {
        tree[node + decal] = val[Lant[poz_l][st - 1]];
        return;
    }

    int mij = (st + dr) >> 1;
    build_tree(st, mij, (node << 1), decal, poz_l);
    build_tree(mij + 1, dr, (node << 1) + 1, decal, poz_l);

    tree[node + decal] = max(tree[(node << 1) + decal], tree[(node << 1) + 1 + decal]);
}

void update(int st, int dr, int node, int poz, int val, int decal) {
    if (st == dr) {
        tree[node + decal] = val;
        return;
    }

    int mij = (st + dr) >> 1;
    if (poz <= mij) {
        update(st, mij, (node << 1), poz, val, decal);
    }
    else {
        update(mij + 1, dr, (node << 1) + 1, poz, val, decal);
    }

    tree[node + decal] = max(tree[(node << 1) + decal], tree[(node << 1) + 1 + decal]);
}

int max_query(int st, int dr, int node, int a, int b, int decal) {
    if (dr < a || st > b) {
        return INT_MIN;
    }
    if (a <= st && dr <= b) {
        return tree[node + decal];
    }

    int mij = (st + dr) >> 1;
    return max(max_query(st, mij, (node << 1), a, b, decal), max_query(mij + 1, dr, (node << 1) + 1, a, b, decal));
}

void build_chains() {
    niv[1] = 1;
    DFS(1);

    for (int i = 1; i <= nr_L; i++) {
        reverse(Lant[i].begin(), Lant[i].end());
        if (i > 1) {
            Ldecal[i] = Ldecal[i - 1] + Lant[i].size() * 4;
        }

        build_tree(1, Lant[i].size(), 1, Ldecal[i], i);
    }
}

void solve() {
    fin >> op >> x >> y;

    if (op == 0) {
        update(1, Lant[L[x]].size(), 1, niv[x] - Lniv[L[x]], y, Ldecal[L[x]]);
    }
    else {
        ans = INT_MIN;

        while (true) {
            if (L[x] == L[y]) {
                if (niv[x] > niv[y]) {
                    swap(x, y);
                }
                ans = max(ans, max_query(1, Lant[L[x]].size(), 1, niv[x] - Lniv[L[x]],
                    niv[y] - Lniv[L[y]], Ldecal[L[x]]));
                break;
            }
            if (Lniv[L[x]] < Lniv[L[y]]) {
                swap(x, y);
            }

            ans = max(ans, max_query(1, Lant[L[x]].size(), 1, 1, niv[x] - Lniv[L[x]], Ldecal[L[x]]));
            x = Lrad[L[x]];
        }
        fout << ans << '\n';
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    fin.tie(NULL);
    fout.tie(NULL);

    fin >> n >> q;
    for (int i = 1; i <= n; i++) {
        fin >> val[i];
    }
    for (int i = 1; i <= n - 1; i++) {
        fin >> x >> y;
        arb[x].push_back(y);
        arb[y].push_back(x);
    }

    build_chains();

    while (q--) {
        solve();
    }
    return 0;
}