Cod sursa(job #3176701)

Utilizator andiRTanasescu Andrei-Rares andiR Data 27 noiembrie 2023 16:59:13
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.57 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

#define pb push_back
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
const int Nmax=1e5+5, Pmax=(1<<17), Vmax=2e6+5;

int n, q;
struct node{
    int v, w, ind, indc, h, p;
    vector<int> ad;
};
struct AINT{
    vector<int> v;
    void build(int n){
        v.resize(n, -1);
    }
    void _update(int nod, int l, int r, int pos, int val){
        if (l==r){
            v[nod]=val;
            return;
        }
        int mij=(l+r)/2;
        if (pos<=mij)
            _update(nod*2, l, mij, pos, val);
        else _update(nod*2+1, mij+1, r, pos, val);
        v[nod]=max(v[nod*2], v[nod*2+1]);
    }
    void update(int pos, int val){
        _update(1, 0, Pmax, pos, val);
    }
    int _querry(int nod, int l, int r, int ql, int qr){
        if (qr<l || r<ql)
            return -1;
        if (ql<=l && r<=qr)
            return v[nod];
        int mij=(l+r)/2;
        return max(_querry(nod*2, l, mij, ql, qr), _querry(nod*2+1, mij+1, r, ql, qr));
    }
    int querry(int l, int r){
        return _querry(1, 0, Pmax, l, r);
    }
};
struct HeavyPath{
    vector<node> V;
    vector<int> fchain;
    AINT aint;

    HeavyPath(int n){
        V.resize(n);
    }

    void _get_w(int nod, int p, int h){
        V[nod].h=h;
        V[nod].p=p;
        for (auto it:V[nod].ad)
            if (it!=p){
                _get_w(it, nod, h+1);
                V[nod].w+=V[it].w;
            }
        V[nod].w++;
    }
    void _build_chain(int nod, int p, int &time, int &chain){
        if (fchain.size()==chain)
            fchain.pb(nod);
        V[nod].ind=time++;
        V[nod].indc=chain;

        int mxw=0, mxi=-1;
        for (auto it:V[nod].ad)
            if (it!=p && mxw<V[it].w){
                mxw=V[it].w;
                mxi=it;
            }
        if (mxi!=-1){
            _build_chain(mxi, nod, time, chain);
            for (auto it:V[nod].ad)
                if (it!=p && it!=mxi)
                    _build_chain(it, nod, time, ++chain);
        }
    }
    inline void partition(){

        _get_w(0, -1, 0);
        int time=0, chain=0;
        _build_chain(0, -1, time, chain);

        aint.build(2*Pmax);
        for (int i=0; i<n; i++)
            aint.update(V[fchain[V[i].indc]].ind+V[i].h-V[fchain[V[i].indc]].h, V[i].v);
    }
    inline void update(int pos, int val){
        V[pos].v=val;
        aint.update(V[fchain[V[pos].indc]].ind+V[pos].h-V[V[pos].indc].h, V[pos].v);
    }
    int querry(int a, int b){
        int ra=fchain[V[a].indc];
        int rb=fchain[V[b].indc];
        int mx=-1;
        while (ra!=rb){
            if (V[ra].h<V[rb].h){
                swap(a, b);
                swap(ra, rb);
            }
            mx=max(mx, aint.querry(V[ra].ind, V[ra].ind+V[a].h-V[ra].h));
            a=V[ra].p;
            ra=fchain[V[a].indc];
        }
        if (V[a].h>V[b].h){
            swap(a, b);
            swap(ra, rb);
        }
        mx=max(mx, aint.querry(V[ra].ind+V[a].h-V[ra].h, V[rb].ind+V[b].h-V[rb].h));
        return mx;
    }

};

int main(){
    fin>>n>>q;
    HeavyPath arb(n);

    for (int i=0; i<n; i++)
        fin>>arb.V[i].v;

    int a, b;
    for (int i=0; i<n-1; i++){
        fin>>a>>b;
        a--; b--;
        arb.V[a].ad.pb(b);
        arb.V[b].ad.pb(a);
    }

    arb.partition();

    int t, x, y;
    for (int i=0; i<q; i++){
        fin>>t>>x>>y;
        if (t==0){
            x--;
            arb.update(x, y);
        }
        else{
            x--; y--;
            fout<<arb.querry(x, y)<<'\n';
        }
    }

    return 0;
}