Cod sursa(job #3224579)

Utilizator maiaauUngureanu Maia maiaau Data 15 aprilie 2024 17:51:35
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.32 kb
#include <bits/stdc++.h>
using namespace std;
#define pb push_back

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

const int N = 1e5+2;

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

void read(), upd(int,int), dfs(int), hld(), updAint(int,int);
int query(int, int), queryAint(int,int,int,int,int);

int main(){
    read();
    hld();
    while (m--){
        int tip, x, y; fin >> tip >> x >> y;
        if (tip) fout << query(x, y) << '\n';
        else {
            upd(x,y);
        }
    }

    return 0;
}

void read() {
    fin >> n >> m;
    while (p < n) p *= 2; p--;
    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 hld() {
    path.pb({});
    dfs(1); int k = 1;
    for (int i = 1; i <= nrp; i++) {
        reverse(path[i].begin(), path[i].end());
        for (auto it: path[i]){
            pos[it] = k + p; 
            a[k + p] = v[it];
            k++;
        }
    }
    for (int i = p; i; i--) a[i] = max(a[2*i], a[2*i+1]);
}
void dfs(int nod) {
    int hvy = 0; 
    sz[nod] = 1;
    niv[nod] = niv[t[nod]] + 1;
    for (auto it: e[nod]){
        if (it == t[nod]) continue;
        t[it] = nod; dfs(it);
        if (sz[it] > sz[hvy]) {hvy = it; ord[nod] = ord[it];}
        sz[nod] += sz[it];
    }   
    if (!hvy){
        nrp++; path.pb({});
        ord[nod] = nrp;
    }
    path[ord[nod]].pb(nod);
}
void upd(int x, int y){
    updAint(pos[x], y);
}
int query(int x, int y){
    int ret = 0;
    while (ord[x] != ord[y]){ //nu sunt pe acelasi lant
        if (niv[x] < niv[y]) swap(x, y);
        ret = max(ret, queryAint(1, 1, p + 1, pos[path[ord[x]][0]] - p, pos[x] - p));
        x = t[path[ord[x]][0]];
    }
    if (niv[x] > niv[y]) swap(x, y);
    ret = max(ret, queryAint(1, 1, p+1, pos[x] - p, pos[y] - p));
    return ret;
}
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));
}
void updAint(int pos, int val){
    v[pos - p] = val;
    a[pos] = val; pos /= 2;
    while (pos){
        a[pos] = max(a[2*pos], a[2*pos+1]);
        pos /= 2;
    }
}