Cod sursa(job #3192327)

Utilizator Radu_MocanasuMocanasu Radu Radu_Mocanasu Data 12 ianuarie 2024 10:21:21
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.08 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector <int> G[100005];
int v[100005];
int nrf[100005];
int t[100005];
int depth[100005];
int pathid[100005];
vector <int> paths[100005];
vector <int> AINT[100005];
int nrpath;
void dfs(int nod, int p){
    int best = 0;
    t[nod] = p;
    nrf[nod] = 1;
    depth[nod] = depth[t[nod]] + 1;
    vector <int> :: iterator it;
    for(it = G[nod].begin(); it != G[nod].end(); it++){
        int x = *it;
        if(!depth[x]){
            dfs(x,nod);
            nrf[nod] += nrf[x];
            if(nrf[x] > nrf[best]) best = x;
        }
    }
    if(!best){
        pathid[nod] = ++nrpath;
        paths[pathid[nod]].push_back(nod);
    }
    else{
        pathid[nod] = pathid[best];
        paths[pathid[best]].push_back(nod);
    }
}
inline int position(int nod){
    return depth[nod] - depth[paths[pathid[nod]][0]] + 1;
}
inline int path_depth(int nod){
    return depth[paths[pathid[nod]][0]];
}
void update_aint(vector <int> &aint, int nod, int st, int dr, int poz, int val){
    if(st == dr){
        aint[nod] = val;
        return;
    }
    int med = (st + dr) >> 1;
    if(poz <= med) update_aint(aint,2 * nod, st, med, poz, val);
    else update_aint(aint,2 * nod + 1, med + 1, dr, poz, val);
    aint[nod] = max(aint[2 * nod], aint[2 * nod + 1]);
}
int query_aint(vector <int> &aint, int nod, int st, int dr, int l, int r){
    if(l <= st && dr <= r) return aint[nod];
    int med = (st + dr) >> 1,a1 = 0,a2 = 0;
    if(l <= med) a1 = query_aint(aint, 2 * nod, st, med, l,r);
    if(r > med) a2 = query_aint(aint, 2 * nod + 1, med + 1, dr, l,r);
    return max(a1,a2);
}
void update_path(int nod, int val){
    v[nod] = val;
    update_aint(AINT[pathid[nod]], 1, 1, paths[pathid[nod]].size(), position(nod), v[nod]);
}
int first_on_path(int nod){
    return paths[pathid[nod]][0];
}
int path_max(int nod1, int nod2){
    int id = pathid[nod1];
    int x = position(nod1);
    int y = position(nod2);
    if(x > y) swap(x,y);
    return query_aint(AINT[id], 1, 1, paths[id].size(), x, y);
}
int query(int x, int y){
    int rez = 0;
    while(pathid[x] != pathid[y]){
        if(path_depth(x) < path_depth(y)) swap(x,y);
        rez = max(rez, path_max(first_on_path(x),x));
        x = t[first_on_path(x)];
    }
    rez = max(rez, path_max(x,y));
    return rez;
}
int main()
{
    int n,i,j,m,u,w;
    fin >> n >> m;
    for(i = 1; i <= n; i++) fin >> v[i];
    for(i = 1; i < n; i++){
        fin >> u >> w;
        G[u].push_back(w);
        G[w].push_back(u);
    }
    dfs(1,0);
    for(i = 1; i <= nrpath; i++){
        reverse(paths[i].begin(), paths[i].end());
        AINT[i] = vector<int>(4 * (int)paths[i].size() + 1, 0);
        vector <int> :: iterator it;
        for(it = paths[i].begin(); it != paths[i].end(); it++) update_path(*it, v[*it]);
    }
    while(m--){
        int c,x,y;
        fin >> c >> x >> y;
        if(!c) update_path(x,y);
        else fout << query(x,y) << "\n";
    }
    return 0;
}