Cod sursa(job #2837751)

Utilizator MocalinnoMoca Andrei Catalin Mocalinno Data 22 ianuarie 2022 14:50:36
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.56 kb
#include <fstream>
#include <vector>
#include <algorithm>

using namespace std;

const string task("heavypath");

ifstream fin(task + ".in");
ofstream fout(task + ".out");

using VI  = vector<int>;
using VVI = vector<VI>;


class SegTree {
public:
    SegTree(VI const& v) {
        for (N = 1; N < static_cast<int>(v.size()); N *= 2);
        tree = VI(2 * N, 0);
        for (size_t i = 0; i < static_cast<int>(v.size()); ++i)
            tree[N + i] = v[i];
        for (int x = N - 1; x > 0; --x)
            tree[x] = max(tree[2 * x], tree[2 * x + 1]);
    }

    inline void Update(int const& pos, int const& val) {
        int p = pos + N;
        tree[p] = val;
        for (p /= 2; p; p /= 2)
            tree[p] = max(tree[2 * p], tree[2 * p + 1]);
    }

    inline int Query(int const& st, int const& dr) const {
        int l = st + N, r = dr + N, ans = 0;
        while (l <= r) {
            ans = max({ans, tree[l], tree[r]});
            l = (l + 1) / 2;
            r = (r - 1) / 2;
        }
        return ans;
    }

private:
    int N;
    VI tree;
};

class HeavyPath {
public:
    HeavyPath(int const& _N = 0)
        : N(_N), g(N + 1), t(N + 1), h(N + 1), nr(N + 1), pId(N + 1), pos(N + 1) {}

    inline void SetValues(VI const& _v) {
        v = _v;
    }

    inline void AddEdge(int const& x, int const& y) {
        g[x].emplace_back(y);
        g[y].emplace_back(x);
    }

    inline void BuildHP() {
        DFS();
        for (VI const& path : paths) {
            VI values;
            for (int const& x : path)
                values.emplace_back(v[x]);
            st.emplace_back(SegTree(values));
        }
    }

    inline int Query(int const& _x, int const& _y) const {
        int x = _x, y = _y;

        if (pId[x] == pId[y]) {
            if (pos[x] > pos[y])
                swap(x, y);
            return st[pId[x]].Query(pos[x], pos[y]);
        }
        if (h[paths[pId[x]].back()] < h[paths[pId[y]].back()])
            swap(x, y);

        int r1 = st[pId[x]].Query(pos[x], static_cast<int>(paths[pId[x]].size()) - 1);
        int r2 = Query(t[paths[pId[x]].back()], y);

        return max(r1, r2);
    }

    inline void Update(int const& x, int const& val) {
        v[x] = val;
        st[pId[x]].Update(pos[x], val);
    }

private:
    inline void DFS(int const& x = 1) {
        int hs = 0;
        nr[x] = 1;

        for (int const& y : g[x]) {
            if (y == t[x])
                continue;
            t[y] = x;
            h[y] = h[x] + 1;
            DFS(y);
            nr[x] += nr[y];
            if (nr[y] > nr[hs])
                hs = y;
        }

        if (!hs) {
            pId[x] = static_cast<int>(paths.size());
            paths.emplace_back(VI());
        }
        else pId[x] = pId[hs];

        pos[x] = static_cast<int>(paths[pId[x]].size());
        paths[pId[x]].emplace_back(x);
    }

    int N;
    VVI g, paths;
    VI v, t, h, nr, pId, pos;
    vector<SegTree> st;
};

int N, Q;
VI v;

int main() {
    fin >> N >> Q;

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

    HeavyPath HP(N);
    HP.SetValues(v);

    for (int i = 1; i < N; ++i) {
        int x, y;
        fin >> x >> y;
        HP.AddEdge(x, y);
    }

    HP.BuildHP();

    while (Q--) {
        int op, x, y;
        fin >> op >> x >> y;
        if (op == 0)
            HP.Update(x, y);
        else fout << HP.Query(x, y) << '\n';
    }

    fin.close();
    fout.close();
    return 0;
}