Cod sursa(job #2846134)

Utilizator OvidRata Ovidiu Ovid Data 8 februarie 2022 19:55:39
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.32 kb
#include<bits/stdc++.h>
using namespace std;
#define INIT  ios_base :: sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#define mp make_pair
#define pb push_back
#define ft first
#define sc second
#define ll long long
#define pii pair<int, int>
#define count_bits __builtin_popcount
//#define int ll


ifstream fin("heavypath.in"); ofstream fout("heavypath.out");
#define cin fin
#define cout fout


int n, m, a[100010];

vector<int> g[100010];



int sz[100010];

int ent[100010], ex[100010];
int tmp=0;


bool v[100010];


int anc[100010][21];


void dfs0(int s){

sz[s]=1;

tmp++;
ent[s]=tmp;
v[s]=true;

for(auto u:g[s]){
    if(!v[u]){
        anc[u][0]=s;
        dfs0(u);
        sz[s]+=sz[u];
    }
}

tmp++;
ex[s]=tmp;
v[s]=false;
return;
}



int rep[100010];
int crd[100010];

void dfs1(int s){

tmp++;
crd[s]=tmp;

int mx=0, node=0;

for(auto u:g[s]){
    if(u!=anc[s][0]){

    if(sz[u]>mx){
        node=u;
        mx=sz[u];
    }

    }
}

if(node!=0){
rep[node]=rep[s];
dfs1(node);

}


for(auto u:g[s]){
    if( (u!=node) && ( u!=anc[s][0] ) ){
        rep[u]=u;
        dfs1(u);
    }
}


}



void build_anc(){

for(int j=1; j<=16; j++){
    for(int i=1; i<=n; i++){
        anc[i][j]=anc[anc[i][j-1] ][j-1];
    }
}

}


bool is_anc(int u, int v){

return (ent[u]<ent[v]) && (ex[u]>ex[v]);

}

int lca(int u, int v){

if(u==v){
    return u;
}

if( is_anc(u, v)){
    return u;
}
if( is_anc(v, u)){
    return v;
}


int res=u;
for(int j=16; j>=0; j--){
    if( (anc[res][j]!=0 ) && (  !is_anc( anc[res][j], v )   ) ){
        res=anc[res][j];
    }
}

return anc[res][0];

}






int b[100010];

int tree[400010];

void build_tree(int v, int l, int r){

if(l==r){
    tree[v]=b[l];
    return;
}

int mid=(l+r)>>1ll;

build_tree(2*v,l, mid); build_tree(2*v+1, mid+1, r);
tree[v]=max(tree[2*v], tree[2*v+1]);

return;
}



void update(int v, int l, int r, int p, int x){

if(l==r){
    b[ crd[p] ]=x;
    tree[v]=b[ crd[p] ];
    return;
}

int mid=(l+r)>>1ll;
if(crd[p]<=mid){
    update(2*v, l, mid, p, x);
}
else{
    update(2*v+1, mid+1, r, p, x);
}
tree[v]=max(tree[v*2], tree[2*v+1]);
return;
}


int query(int v, int tl, int tr, int l, int r){

if(l>r){
    return -1;
}

if( (tl==l) && (tr==r)){
    return tree[v];
}

int mid=(tl+tr)>>1ll;
return max(   query(2*v, tl, mid, l, min(r, mid)), query(2*v+1, mid+1, tr,  max(l, mid+1), r )  );
}




int32_t main(){
INIT
cin>>n>>m;
for(int i=1; i<=n; i++){
    cin>>a[i];
}
for(int i=1; i<n; i++){
    int u, v;
    cin>>u>>v;
    g[u].pb(v); g[v].pb(u);
}

dfs0(1);

build_anc();

tmp=0;
rep[1]=1;
dfs1(1);




for(int i=1; i<=n; i++){
    b[crd[i] ]=a[i];
}

build_tree(1, 1, n);



for(int i=1; i<=m; i++){
    int t;
    cin>>t;
    if(t==0){
        int p, x;
        cin>>p>>x;
        update(1, 1, n, p, x);
    }
    else{
        int u, v;
        cin>>u>>v;
        int LCA=lca(u, v);

        int mx1=0, mx2=0;

        int ac=u;
        while(true){
            if( rep[ac]!=LCA ){
                if(  (is_anc(rep[ac], LCA)) ){
                    mx1=max(mx1, query(1, 1, n, crd[ LCA], crd[ac]) );
                    break;
                }
                else{
                    mx1=max(mx1, query( 1, 1, n, crd[ rep[ac] ], crd[ac ]) );
                    ac=anc[ rep[ac] ][0];
                    continue;
                }
            }
            else{

                mx1=max(mx1, query( 1, 1, n, crd[ rep[ac] ], crd[ac ]) );
                break;

            }
        }

        ac=v;

        while(true){

        if(rep[ac]!=LCA){

            if(is_anc(rep[ac], LCA )){
                mx2=max(mx2, query(1, 1, n, crd[LCA], crd[ac] ) );
                break;
            }
            else{
                mx2=max( mx2, query(1, 1, n, crd[rep[ac] ], crd[ac]) );
                ac=anc[rep[ac] ][0];
                continue;
            }

        }
        else{
            mx2=max(mx2, query(1, 1, n, crd[rep[ac] ], crd[ac] ) );
            break;
        }

        }

        cout<<max(mx1, mx2)<<"\n";

    }
}

return 0;
}