Cod sursa(job #2885351)

Utilizator Cosmin2004_InfoMoldoveanu Cosmin Cosmin2004_Info Data 5 aprilie 2022 20:39:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.7 kb
#include <bits/stdc++.h>

using namespace std;
#ifndef HOME
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
#else
ifstream fin("ciorna.in");
ofstream fout("ciorna.out");
#endif
class HeavyPath {
    int n;
    vector <vector <int>>& g;
    vector <int> path, trans, sz, h, head, t;
    int k;
    vector <vector <int>> decomp;
    void dfs(int u, int p) {
        h[u] = h[p] + 1;
        int link = 0;
        for(int v : g[u]) if(v != p) {
            dfs(v, u);
            sz[u] += sz[v];
            if(sz[v] > sz[link]) link = v;
        }
        if(!link) {
            decomp.push_back({u});
            path[u] = k++;
        } else {
            path[u] = path[link];
            decomp[path[u]].push_back(u);
            for(int v : g[u]) if(v != p && v != link)
                head[path[v]] = u;
        }
    }
    void light_update(int pos, int val) { for(t[pos += n] = val; pos > 1; pos >>= 1) t[pos >> 1] = max(t[pos], t[pos ^ 1]); }
    int heavy_query(int l, int r) {
        int res = 0;
        for(l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if(l & 1) res = max(res, t[l++]);
            if(r & 1) res = max(res, t[--r]);
        }
        return res;
    }
public:
    HeavyPath(int n, vector <vector <int>>& g, int* v) : n(n), g(g), path(n + 1, 0), trans(n + 1, 0), sz(n + 1, 1), h(n + 1, 0), head(n + 1, 0), t(2 * n, 0), k(0) {
        sz[0] = 0;
        dfs(1, 0);
        int curr = 0;
        for(auto& pth : decomp)
            for(int u : pth)
                trans[u] = curr++;
        for(int i = 1; i <= n; i++)
            t[trans[i] + n] = v[i];
        for(int i = n - 1; i > 0; i--)
            t[i] = max(t[i << 1], t[i << 1 | 1]);
    }
    void update(int u, int val) { return light_update(trans[u], val); }
    int query(int u, int v) {
        int res = 0;
        while(path[u] != path[v]) {
            if(h[head[path[u]]] < h[head[path[v]]]) swap(u, v);
            res = max(res, heavy_query(trans[u], trans[u] + h[u] - h[head[path[u]]]));
            u = head[path[u]];
        }
        if(h[u] < h[v]) swap(u, v);
        res = max(res, heavy_query(trans[u], trans[v] + 1));
        return res;
    }
};
const int N = 1e5;
int v[N + 5];
vector <vector <int>> g;

int main()
{
    int n, m;
    fin >> n >> m;
    for(int i = 1; i <= n; i++)
        fin >> v[i];
    g.resize(n + 1);
    for(int i = 1, u, v; i < n; i++)
        fin >> u >> v,
        g[u].push_back(v),
        g[v].push_back(u);
    HeavyPath HLD(n, g, v);
    for(int i = 1, t, x, y; i <= m; i++) {
        fin >> t >> x >> y;
        if(!t) HLD.update(x, y);
        else fout << HLD.query(x, y) << "\n";
    }
    return 0;
}