Cod sursa(job #3143485)

Utilizator SerbanCaroleSerban Carole SerbanCarole Data 30 iulie 2023 16:22:05
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.52 kb
#include <fstream>
#include <vector>
#define pb push_back
using namespace std;
using pii = pair<int,int>;

ifstream cin("heavypath.in");
ofstream cout("heavypath.out");

const int MAX = 1e5 + 1;

int n , q , aint[4*MAX] , nrd[MAX] , v[MAX] , wo[MAX] , hn , x , y , lift[18][MAX] , depth[MAX];
int poz[MAX] , ind;

vector <int> f(MAX);
vector <pii> in(MAX);
vector <int> st;
vector <int> g[MAX];

void update( int nod , int st , int dr ,int &poz , int &val){

    if(st==dr){

        aint[nod] = val;

    }else{

        int mij = (st+dr)/2;
        if(poz <= mij) update(nod*2,st,mij,poz,val);
        else update(nod*2+1,mij+1,dr,poz,val);

        aint[nod] = max(aint[nod*2],aint[nod*2+1]);
    }
}

int query( int nod , int st , int dr , int &qst , int &qdr){

    if(qst<=st && dr<=qdr){

        return aint[nod];

    }else{

        int val = -1;
        int mij = (st+dr)/2;
        if(qst <= mij) val = max(val,query(nod*2,st,mij,qst,qdr));
        if(qdr > mij) val = max(val,query(nod*2+1,mij+1,dr,qst,qdr));
        return val;
    }
}

void dfs( int x , int p ){

    depth[x] = depth[p]+1;

    lift[0][x] = p;

    for(int i = 1 ; i <= 17 ; i++){

        lift[i][x] = lift[i-1][lift[i-1][x]];
    }

    for(auto it : g[x]){

        if(it!=p){

            dfs(it,x);
            nrd[x]+=nrd[it];
        }
    }

    nrd[x]++;
    bool is = 0;

    for(auto it : g[x]){

        if(it!=p){

            if(nrd[it]>=nrd[x]/2){

                is = 1;
            }
        }
    }

    if(!is) st.push_back(x);
}

int lca( int a , int b ){

    if(depth[a] > depth[b]){

        swap(a,b);
    }

    int val = depth[b]-depth[a];

    int i = 0;

    while(val){

        if(val%2) b = lift[i][b];

        val = val/2;

        i++;
    }

    if(a==b) return a;

    int pw = 17;

    while(pw>=0){

        if(lift[pw][a]!=lift[pw][b]){
            a = lift[pw][a];
            b = lift[pw][b];
        }
        pw--;
    }

    return lift[0][a];
}

signed main(){

    cin >> n >> q;

    for(int i = 1 ; i <= n ; i++){

        cin >> v[i];
    }

    for(int i = 1 ; i < n ; i++){

        cin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }

    dfs(1,0);

    for(auto it : st){

        int k = 0;

        ++hn;

        while(it>0 && nrd[it] >= nrd[lift[0][it]]/2){
            wo[it] = hn;
            f[hn] = it;
            k++;
            ind++;
            update(1,1,n,ind,v[it]);
            poz[it] = ind;
            it = lift[0][it];
        }

        if(it!=0){
            wo[it] = hn;
            f[hn] = it;
            k++;
            ind++;
            update(1,1,n,ind,v[it]);
            poz[it] = ind;
        }

        in[hn] =  make_pair(ind - k + 1,ind);
    }

    int op , a , b;

    while(q--){

        cin >> op >> a >> b;
        if(!op){

            update(1,1,n,poz[a],b);

        }else{

            int c = lca(a,b);

            int mx = -1;

            while(wo[a]!=wo[c]){
                mx = max(mx,query(1,1,n,poz[a],poz[f[wo[a]]]));
                a = lift[0][f[wo[a]]];
            }

            mx = max(mx,query(1,1,n,poz[a],poz[c]));

            while(wo[b]!=wo[c]){
                mx = max(mx,query(1,1,n,poz[b],poz[f[wo[b]]]));
                b = lift[0][f[wo[b]]];
            }

            mx = max(mx,query(1,1,n,poz[b],poz[c]));

            cout << mx << '\n';
        }
    }

    return 0;
}