Cod sursa(job #2814894)

Utilizator RaresFelixTudose Rares Felix RaresFelix Data 8 decembrie 2021 19:22:56
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.47 kb
#include <bits/stdc++.h>
#define MN 107171
using namespace std;

ifstream fi("heavypath.in");
ofstream fo("heavypath.out");
int n, m, Val[MN];
vector<int> L[MN];

struct AINT {
    int V[4 * MN];
    void build(int u, int s, int d, int* O) {
        if(s == d) {
            V[u] = O[s];
            return;
        }
        build(u * 2, s, (s + d) / 2, O);
        build(u * 2 + 1, (s + d) / 2 + 1, d, O);
        V[u] = max(V[u * 2], V[u * 2 + 1]);
    }

    void update(int p, int v, int u = 1, int s = 1, int d = MN - 1) {
        if(d < p || p < s) return;
        if(s == d) {
            V[u] = v;
            return;
        }
        update(p, v, u * 2, s, (s + d) / 2);
        update(p, v, u * 2 + 1, (s + d) / 2 + 1, d);
        V[u] = max(V[u * 2], V[u * 2 + 1]);
    }

    int query(int l, int r, int u = 1, int s = 1, int d = MN - 1) {
        if(d < l || r < s) return 0;
        if(l <= s && d <= r) return V[u];
        return max(query(l, r, u * 2, s, (s + d) / 2), query(l, r, u * 2 + 1, (s + d) / 2 + 1, d));
    }

};


struct HeavyPath {
    AINT Arbore;
    int Sum[MN], Niv[MN], FiuAles[MN];
    int nrseg, St[MN], Nr[MN], H[MN], Cul[MN]; // AINT
    int Par[MN], PaterFam[MN];

    int ST[20][MN];

    int lca(int u, int v) {
        if(Niv[u] < Niv[v]) swap(u, v);
        for(int k = 19, d = Niv[u] - Niv[v]; k >= 0; --k)
            if(d & (1 << k)) u = ST[k][u];
        if(u == v) return u;
        for(int k = 19; k >= 0; --k)
            if(ST[k][u] != ST[k][v]) u = ST[k][u], v = ST[k][v];
        return ST[0][u];
    }

    void id_dfs(int u, int p, int niv) {
        Sum[u] = 1;
        Niv[u] = niv;
        int ma = 0, sma = -1;
        for(auto it : L[u]) if (it != p) {
            id_dfs(it, u, niv + 1);
            Sum[u] += Sum[it];
            if(Sum[it] > sma) {
                sma = Sum[it];
                ma = it;
            }
        }
        FiuAles[u] = ma;
    }

    void cul_dfs(int u, int p, int color, int h) {
        ++Nr[color];
        Cul[u] = color;
        H[u] = h;
        if(!h) PaterFam[color] = u;
        Par[u] = p;
        for(auto it : L[u]) if (it != p) {
            if(it == FiuAles[u]) cul_dfs(it, u, color, h + 1);
            else cul_dfs(it, u, ++nrseg, 0);
        }
    }

    void build() {
        id_dfs(1, -1, 0);
        cul_dfs(1, -1, (nrseg = 1), 0);
        for(int i = 1; i <= nrseg; ++i) {
            St[i] = Nr[i - 1] + 1;
            Nr[i] += Nr[i - 1];
        }
        for(int i = 1; i <= n; ++i) Arbore.update(St[Cul[i]] + H[i], Val[i]);


        for(int i = 1; i <= n; ++i) ST[0][i] = Par[i];
        for(int k = 1; k < 20; ++k)
            for(int i = 1; i <= n; ++i) ST[k][i] = ST[k-1][ST[k-1][i]];
    }

    void update(int p, int v) {
        Arbore.update(St[Cul[p]] + H[p], v);
    }

    int solve(int fiu, int par) {
        if(Cul[fiu] == Cul[par]) return Arbore.query(St[Cul[par]] + H[par], St[Cul[fiu]] + H[fiu]);
        else return max(solve(fiu, PaterFam[Cul[fiu]]), solve(Par[PaterFam[Cul[fiu]]], par));
    }

    int query(int u, int v) {
        int l = lca(u, v);
        return max(solve(u, l), solve(v, l));
    }
};

HeavyPath Sol;
int main() {
    fi >> n >> m;
    for(int i = 1; i <= n; ++i) fi >> Val[i];
    for(int i = 1, u, v; i < n; ++i) {
        fi >> u >> v;
        L[u].push_back(v);
        L[v].push_back(u);
    }
    Sol.build();
    for(int i = 1, tip, a, b; i <= m; ++i) {
        fi >> tip >> a >> b;
        if(tip) fo << Sol.query(a, b) << "\n";
        else Sol.update(a, b);
    }
    return 0;
}