Cod sursa(job #3030363)

Utilizator florinrafiliuRafiliu Florin florinrafiliu Data 17 martie 2023 17:14:15
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3 kb
#include <iostream>
#include <vector>
#include <set>
#include <fstream>

#define int long long
using namespace std;

ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");

const int maxN = 1e5 + 5;

vector <int> g[maxN], subTree[maxN], euler;
int level[maxN], parent[maxN], sSize[maxN], id[maxN], head[maxN], v[maxN];
int arb[4*maxN];

void update (int k, int st, int dr, int poz, int val) {
    if(st == dr && st == poz) {
        arb[k] = val;
        return ;
    }

    int mij = (st + dr) / 2;

    if(poz <= mij)
        update(k*2, st, mij, poz, val);
    else
        update(k*2+1, mij+1, dr, poz, val);

    arb[k] = max(arb[k*2], arb[k*2+1]);
}

int query (int k, int st, int dr, int l, int r) {
    if(l <= st && dr <= r)
        return arb[k];

    int mij = (st + dr) / 2;

    if(r <= mij)
        return query(k*2, st, mij, l, r);
    else if(l > mij)
        return query(k*2+1, mij+1, dr, l, r);
    else
        return  max(query(k*2, st, mij, l, r),
             query(k*2+1, mij+1, dr, l, r));
}

void compute (int node, int dad = 0) {
    level[node] = level[dad] + 1;
    parent[node] = dad;
    sSize[node] = 1;

    for(int to : g[node]) {
        if(to != dad) {
            compute(to, node);

            sSize[node] += sSize[to];
            subTree[node].push_back(to);
        }
    }
}

void heavyDfs (int node) {
    euler.push_back(node);
    id[node] = euler.size();

    if(subTree[node].size() == 0)
        return ;

    int heavySon = subTree[node][0];
    for(int to : subTree[node])
        if(sSize[to] > sSize[heavySon])
            heavySon = to;

    head[heavySon] = head[node];
    heavyDfs(heavySon);

    for(int to : subTree[node])
        if(to != heavySon)
            heavyDfs(to);
}

int solve (int u, int v, int n) {
    if(head[u] == head[v]) {
        return query(1, 1, n, min(id[u], id[v]), max(id[u], id[v]));
    }

    //cout << u << " " << v << " -> ";
    int ans = 0;
    if(level[parent[head[u]]] > level[parent[head[v]]]) {
        ans = query(1, 1, n, id[head[u]], id[u]);
        u = parent[head[u]];
    } else {
        ans = query(1, 1, n, id[head[v]], id[v]);
        v = parent[head[v]];
    }
    //cout << ans << " -> " <<u << " " << v << '\n';
    return max(ans, solve(u, v, n));
}

signed main() {

    int n, q; fin >> n >> q;

    for(int i = 1; i <= n; i++) {
        fin >> v[i];
        head[i] = i;
    }

    for(int i = 1; i < n; i++) {
        int u, v; fin >> u >> v;

        g[u].push_back(v);
        g[v].push_back(u);
    }

    compute (1);
    heavyDfs(1);

    for(int i = 1; i <= n; i++)
        update(1, 1, n, id[i], v[i]);

    for(int i = 1; i <= q; i++) {
        int op; fin >> op;

        if(op == 0) {
            int poz, val; fin >> poz >> val;
            update(1, 1, n, id[poz], val);
        } else {
            int a, b; fin >> a >> b;
            fout << solve(a, b, n) << "\n";
        }
    }

    return 0;
}