Cod sursa(job #2986775)

Utilizator BlueLuca888Girbovan Robert Luca BlueLuca888 Data 1 martie 2023 09:43:48
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.44 kb
#include <bits/stdc++.h>

using namespace std;

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

const int LIM = 100'000;
int n, v[LIM + 5], w[LIM + 5];
int q, t, x, y;
vector <int> edge[LIM + 5];

int subarbore[LIM + 5], parent[LIM + 5], level[LIM + 5];
inline void calc_subarbore(int crt, int prv){
    parent[crt] = prv;
    level[crt] = level[prv] + 1;
    subarbore[crt] = 1;
    for(auto nxt : edge[crt])
        if(nxt != prv){
            calc_subarbore(nxt, crt);
            subarbore[crt] += subarbore[nxt];
        }
}

int m, index_norm[LIM + 5];
int head_lant[LIM + 5], freq_lant[LIM + 5];
inline void create_lant(int crt, int prv, int hl){
    head_lant [crt] = hl;
    index_norm[crt] = ++m;

    int maxv = 0, maxs = -1;
    for(auto nxt : edge[crt])
        if(nxt != prv){
            if(subarbore[nxt] > maxv){
                maxv = subarbore[nxt];
                maxs = nxt;
            }
        }
    if(maxs != -1){
        create_lant(maxs, crt, hl);
        for(auto nxt : edge[crt])
            if(nxt != prv && nxt != maxs)
                create_lant(nxt, crt, nxt);
    }
}

struct SEGTREE{
    int aint[4 * LIM + 5];

    inline void build(int nod=1, int st=1, int dr=n){
        if(st == dr){
            aint[nod] = w[st];
        }else{
            int md = ((st + dr) >> 1);
            build(2*nod  , st  , md);
            build(2*nod+1, md+1, dr);
            aint[nod] = max(aint[2*nod], aint[2*nod+1]);
        }
    }

    inline void update(int poz, int val, int nod=1, int st=1, int dr=n){
        if(st == dr){
            aint[nod] = val;
        }else{
            int md = ((st + dr) >> 1);
            if(poz <= md) update(poz, val, 2*nod  , st  , md);
            if(poz >  md) update(poz, val, 2*nod+1, md+1, dr);
            aint[nod] = max(aint[2*nod], aint[2*nod+1]);
        }
    }

    inline int query(int qst, int qdr, int nod=1, int st=1, int dr=n){
        if(qst <= st && dr <= qdr){
            return aint[nod];
        }else{
            int md = ((st + dr) >> 1), answer = 0;
            if(qst <= md) answer = max(answer, query(qst, qdr, 2*nod  , st  , md));
            if(qdr >  md) answer = max(answer, query(qst, qdr, 2*nod+1, md+1, dr));
            return answer;
        }
    }
} tree;

inline int query_lant(int nod1, int nod2){
    int answer = 0;
    while(head_lant[nod1] != head_lant[nod2]){
        if(level[head_lant[nod1]] < level[head_lant[nod2]])
            swap(nod1, nod2);

        answer = max(answer, tree.query(index_norm[ head_lant[nod1] ], index_norm[ nod1 ]));
        nod1 = parent[head_lant[nod1]];
    }

    if(index_norm[nod1] > index_norm[nod2])
        swap(nod1, nod2);
    answer = max(answer, tree.query(index_norm[nod1], index_norm[nod2]));
    return answer;
}

int main (){
    ios_base::sync_with_stdio(false);
    fin.tie(nullptr), fout.tie(nullptr);

    fin>>n>>q;

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

    for(int i=1, u, v; i < n; i++){
        fin>>u>>v;
        edge[u].push_back(v);
        edge[v].push_back(u);
    }

    calc_subarbore(1, 0);
    create_lant(1, 0, 1);

    for(int i=1; i<=n; i++)
        w[index_norm[i]] = v[i];

    tree.build();
    while(q--){
        fin>>t>>x>>y;
        if(t == 0){ ///update
            tree.update(x, y);
        }else{ ///query
            fout<<query_lant(x, y)<<"\n";
        }
    }
    return 0;
}