Cod sursa(job #2986760)

Utilizator ArdeleanOficialAlexandru ArdeleanOficial Data 1 martie 2023 04:43:57
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.59 kb
#include <fstream>
#include <vector>

using namespace std;

const int N = 1e5 + 7;

namespace LI {
    int ant[N], ult[N], v[N];

    int timp;

    void add(int a, int b) {
        ant[++timp] = ult[a];
        ult[a] = timp;
        v[timp] = b;
    }
}

namespace AINT { ///maxim pe interval, update pe nod
    int t[2 * N];

    int n;

    void SetN(int _n) {
        n = _n;
    }

    void UpdatePreBuild(int p, int v) {
        t[p + n] = v;
    }

    void Build() {
        for (int p = n - 1; p; --p)
            t[p] = max(t[p << 1], t[p << 1 | 1]);
    }

    void Update(int p, int v) {
        p--;
        for (t[p += n] = v; p > 1; p >>= 1)
            t[p >> 1] = max(t[p], t[p ^ 1]);
    }

    int Query(int l, int r) {///[l, r) indexat de la 0
        ++r;
        int a(0);
        for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
            if (l & 1)
                a = max(a, t[l++]);
            if (r & 1)
                a = max(a, t[--r]);
        }
        return a;
    }

    int Query(const vector < pair < int, int > > &intervale) {
        int a(0);
        for (auto i : intervale)
            a = max(a, Query(i.first, i.second));
        return a;
    }
}

namespace HLD {
    int head[N], p[N], g[N], h[N], t[N];

    int timp;

    void dfsG(int u) {
        g[u] = 1;
        for (int i = LI::ult[u]; i; i = LI::ant[i]) {
            int v = LI::v[i];
            if (v == t[u])
                continue;
            h[v] = 1 + h[u];
            t[v] = u;
            dfsG(v);
            g[u] += g[v];
        }
    }

    void dfsHLD(int u) {
        int heavyW(0);
        for (int i = LI::ult[u]; i; i = LI::ant[i]) {
            int v = LI::v[i];
            if (v == t[u])
                continue;

            if (heavyW == 0 || g[heavyW] < g[v])
                heavyW = v;
        }

        if (!heavyW)
            return;

        head[heavyW] = head[u];
        p[heavyW] = ++timp;
        dfsHLD(heavyW);

        for (int i = LI::ult[u]; i; i = LI::ant[i]) {
            int v = LI::v[i];
            if (v == t[u] || head[v])
                continue;

            head[v] = v;
            p[v] = ++timp;
            dfsHLD(v);
        }
    }

    void Build() {
        dfsG(1);

        head[1] = 1;
        dfsHLD(1);
    }

    vector < pair < int, int > > GetIntervals(int u, int v) {
        vector < pair < int, int > > a;

        while (head[u] != head[v]) {
            if (h[head[u]] < h[head[v]])
                swap(u, v);

            a.push_back({p[head[u]], p[u]});
            u = t[head[u]];
        }

        a.push_back({min(p[u], p[v]), max(p[u], p[v])});
        return a;
    }
}

int v[N];

int main()
{
    ///m-am gandit sa fac o parcurgere dfs sa renotez nodurile sa fie calculele mai cache friendly, dar am doar doua dfs-uri si sa fac trei sa fie doua mai cache friendly nu merita
    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");
    int n, q;
    fin >> n >> q;

    AINT::SetN(n);
    for (int i = 1; i <= n; ++i)
        fin >> v[i];
    for (int i = 1; i < n; ++i) {
        int u, v;
        fin >> u >> v;
        LI::add(u, v);
        LI::add(v, u);
    }
    HLD::Build();
    for (int i = 1; i <= n; ++i)
        AINT::UpdatePreBuild(HLD::p[i], v[i]);
    AINT::Build();

    while (q--) {
        int t, a, b;
        fin >> t >> a >> b;

        if (t)
            fout << AINT::Query(HLD::GetIntervals(a, b)) << '\n';
        else
            AINT::Update(a, b);
    }

    return 0;
}