Cod sursa(job #3251824)

Utilizator Raul_AArdelean Raul Raul_A Data 27 octombrie 2024 10:25:12
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.91 kb
#include <fstream>
#include <climits>
#include <algorithm>
#include <vector>
#include <bitset>
using namespace std;

const string fn("heavypath");

ifstream in(fn + ".in");
ofstream out(fn + ".out");

#define cin in
#define cout out

const int MAX = 1e5;

int n, q, val[MAX + 5], niv[MAX + 5], w[MAX + 5], nrL, L[MAX + 5], Lfather[MAX + 5], Lniv[MAX + 5], Ldecal[MAX + 5];
int Tree[4 * MAX + 5];
vector<int> g[MAX + 5], Lant[MAX + 5];
bitset<MAX + 5> viz;

void dfs(int node) {
    viz[node] = 1;
    w[node] = 1;
    int leaf = 1, maxl = -1;

    for (auto x : g[node]) {
        if (viz[x]) {
            continue;
        }
            
        leaf = 0;
        niv[x] = niv[node] + 1;

        dfs(x);

        w[node] += w[x];

        if (maxl == -1) {
            maxl = x;
        }
        else if (w[maxl] < w[x]) {
            maxl = x;
        }
    }

    if (leaf) {
        nrL++;
        L[node] = nrL;
        Lant[L[node]].push_back(node);
    }
    else {
        L[node] = L[maxl];
        Lant[L[node]].push_back(node);

        for (auto x : g[node]) {
            if (x == maxl or niv[x] < niv[node]) {
                continue;
            }
                
            Lfather[L[x]] = node;
            Lniv[L[x]] = niv[node];
        }
    }
}

void build(int node, int l, int r, int decal, int pozl) {
    if (l == r) {
        Tree[node + decal] = val[Lant[pozl][l - 1]];
    }
    else {
        int m = (l + r) / 2;

        build(2 * node, l, m, decal, pozl);
        build(2 * node + 1, m + 1, r, decal, pozl);

        Tree[node + decal] = max(Tree[2 * node + decal], Tree[2 * node + 1 + decal]);
    }
}

void update(int node, int l, int r, int target, int val, int decal) {
    if (l == r) {
        Tree[node + decal] = val;
    }
    else {
        int m = (l + r) / 2;

        if (target <= m) {
            update(2 * node, l, m, target, val, decal);
        }
        else {
            update(2 * node + 1, m + 1, r, target, val, decal);
        }

        Tree[node + decal] = max(Tree[2 * node + decal], Tree[2 * node + 1 + decal]);
    }
}

int query(int node, int l, int r, int a, int b, int decal) {
    if (r < a or b < l) {
        return INT_MIN;
    }
        
    if (a <= l and r <= b) {
        return Tree[node + decal];
    }

    int m = (l + r) / 2;

    return max(query(2 * node, l, m, a, b, decal), query(2 * node + 1, m + 1, r, a, b, decal));
}

void make_paths() {
    niv[1] = 1;

    dfs(1);

    for (int i = 1; i <= nrL; i++) {
        reverse(Lant[i].begin(), Lant[i].end());

        if (i > 1) {
            Ldecal[i] = Ldecal[i - 1] + Lant[i - 1].size() * 4;
        }
            
        build(1, 1, Lant[i].size(), Ldecal[i], i);
    }
}

void solve() {
    int t, x, y;

    cin >> t >> x >> y;

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

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

        cout << ans << '\n';
    }
}

int main() {
    cin >> n >> q;

    for (int i = 1; i <= n; i++) {
        cin >> val[i];
    }
        
    for (int i = 1, x, y; i < n; i++) {
        cin >> x >> y;

        g[x].push_back(y);
        g[y].push_back(x);
    }

    make_paths();

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