Cod sursa(job #3225283)

Utilizator maiaauUngureanu Maia maiaau Data 17 aprilie 2024 11:37:53
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.18 kb
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
using ll = long long;

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

const int N = 1e5+3;

int n, m, nrp, p = 1, v[N], wp[N], sz[N], niv[N], t[N], a[4*N], pos[N];
vector<int> e[N];
vector<vector<int>> path;

void read(), hpd(), dfs(int), updAint(int,int);
int query(int,int), queryAint(int,int,int,int,int);

int main()
{
    read();
    hpd();
    while (m--) {
        int tip, x, y; fin >> tip >> x >> y;
        if (tip) fout << query(x, y) << '\n';
        else updAint(pos[x], y);
    }
}

void read() {
    fin >> n >> m; 
    for (int i = 1; i <= n; i++) fin >> v[i];
    for (int i = 1; i < n; i++){
        int x, y; fin >> x >> y;
        e[x].pb(y); e[y].pb(x);
    }
}
void hpd() {
    dfs(1);
    int k = 1;
    while (p < n) p *= 2; p--;

    for (auto &pth: path){
        reverse(pth.begin(), pth.end());
        for (auto el: pth) {
            a[k + p] = v[el];
            pos[el] = k++;
        }
    }
    for (int i = p; i; i--) 
        a[i] = max(a[2*i], a[2*i+1]);
}
void dfs(int nod) {
    niv[nod] = niv[t[nod]] + 1;
    sz[nod] = 1;
    int mx = 0;
    for (auto it: e[nod]) {
        if (it == t[nod]) continue;
        t[it] = nod; dfs(it);
        if (sz[it] > sz[mx]){
            mx = it;
            wp[nod] = wp[it];
        }
        sz[nod] += sz[it];
    }
    if (!mx){
        path.pb({}); 
        wp[nod] = nrp; nrp++;
    }
    path[wp[nod]].pb(nod);
}
void updAint(int k, int val){
    k += p; a[k] = val; k /= 2;
    while (k) { a[k] = max(a[2 * k], a[2 * k + 1]); k /= 2; }
}
int queryAint(int nod, int l, int r, int ql, int qr){
    if (r < ql || qr < l) return 0;
    if (ql <= l && r <= qr) return a[nod];
    int mi = (l + r) / 2;
    return max(queryAint(2*nod, l, mi, ql, qr), queryAint(2*nod+1, mi+1, r, ql, qr));
}
int query(int x, int y) {
    int ret = 0;
    while (wp[x] != wp[y]){
        if (niv[path[wp[x]][0]] < niv[path[wp[y]][0]])
            swap(x, y);
        ret = max(ret, queryAint(1, 1, p+1, pos[path[wp[x]][0]], pos[x]));
        x = t[path[wp[x]][0]];
    }
    if (niv[x] > niv[y]) swap(x, y);
    ret = max(ret, queryAint(1, 1, p + 1, pos[x], pos[y]));
    return ret;
}