Cod sursa(job #2579839)

Utilizator bigmixerVictor Purice bigmixer Data 12 martie 2020 21:00:19
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.16 kb
#include <bits/stdc++.h>
#define ll long long
#define all(a) (a).begin(), (a).end()
//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define sz() size()
#define fr first
#define sc second
#define pb push_back
#define er erase
#define in insert
#define pi pair<int,int>
#define pii pair<pair<int,int>,int>
#define mp make_pair
//#define int long long
#define rc(s) return cout<<s,0
#define rcc(s) cout<<s,exit(0)
using namespace std;

const int mod=1e9+7;
const int modu=1999999973;
const int modul=998244353;

int n,m,val[100005],dp[100005],indx;
int pathid[100005],pathsize[100005],niv[100005],pathtata[100005];
int pathlvl[100005],tree[600005],pathdecalaj[100005];
bitset<100005>viz;
vector<int>nod[100005],path[100005];

void DFS1(int s){
    int frunza = 1;
    viz[s] = dp[s] = 1;
    int heavyN = -1;
    for(auto it:nod[s]){
        if(!viz[it]){
            frunza=0;
            niv[it]=niv[s]+1;
            DFS1(it);
            dp[s]+=dp[it];
            if(heavyN==-1) heavyN=it;
            else{
                if(dp[it]>dp[heavyN]) heavyN=it;
            }
        }
    }
    if(frunza){
        pathid[s]=(++indx);
        pathsize[indx]++;
        path[indx].push_back(s);
        return;
    }
    pathid[s]=pathid[heavyN];
    pathsize[pathid[s]]++;
    path[pathid[s]].push_back(s);
    for(auto it:nod[s]){
        if(it==heavyN || niv[it]<niv[s]) continue;
        else{
            pathtata[pathid[it]]=s;
            pathlvl[pathid[it]]=niv[s];
        }
    }
    return;
}

void build(int l,int r,int lant,int decalaj,int nod){
    if(l==r){
        tree[nod+decalaj] = val[path[lant][l-1]];
    }
    else{
        int mid=l+(r-l)/2;
        build(l,mid,lant,decalaj,2*nod);
        build(mid+1,r,lant,decalaj,2*nod+1);
        tree[nod+decalaj]=max(tree[2*nod+decalaj],tree[2*nod+1+decalaj]);
        return;
    }
}

void update(int l,int r,int poz,int val,int decalaj,int nod){
    if(l==r){
        tree[nod+decalaj]=val;
        return;
    }
    else{
        int mid=l+(r-l)/2;
        if(poz<=mid) update(l,mid,poz,val,decalaj,2*nod);
        else update(mid+1,r,poz,val,decalaj,2*nod+1);
        tree[nod+decalaj]=max(tree[2*nod+decalaj],tree[2*nod+1+decalaj]);
        return;
    }
}

int query(int l,int r,int le,int re,int decalaj,int nod){
    if(l>re || r<le) return 0;
    else if(l>=le && r<=re) return tree[nod+decalaj];
    else{
        int mid=l+(r-l)/2;
        return max(query(l,mid,le,re,decalaj,2*nod),query(mid+1,r,le,re,decalaj,2*nod+1));
    }
}

int32_t main(){
    ios_base::sync_with_stdio(false);cin.tie(0);cerr.tie(0);cout.tie(0);
    srand(chrono::steady_clock::now().time_since_epoch().count());
    ifstream cin("heavypath.in");
    ofstream cout("heavypath.out");
    cin >> n >> m;
    for(int i=1;i<=n;i++) cin >> val[i];
    for(int i=1;i<n;i++){
        int x,y;
        cin >> x >> y;
        nod[x].push_back(y);
        nod[y].push_back(x);
    }
    niv[1]=1;
    DFS1(1);
    for(int i=1;i<=indx;i++) reverse(all(path[i]));
    for(int i=1;i<=indx;i++){
        if(i>1) pathdecalaj[i]=pathdecalaj[i-1]+4*pathsize[i-1];
        build(1,pathsize[i],i,pathdecalaj[i],1);
    }
    for(int i=1;i<=m;i++){
        int t,x,y ;
        cin >> t >> x >> y;
        if(t==0){
            update(1,pathsize[pathid[x]],niv[x]-pathlvl[pathid[x]],y,pathdecalaj[pathid[x]],1);
        }
        else{
            int ans=0;
            while(true){
                if(pathid[x]==pathid[y]){
                    if(niv[x]>niv[y]) swap(x,y);
                    ans=max(ans,query(1,pathsize[pathid[x]],niv[x]-pathlvl[pathid[x]],niv[y]-pathlvl[pathid[y]],pathdecalaj[pathid[x]],1));
                    break;
                }
                else{
                    if(pathlvl[pathid[x]]<pathlvl[pathid[y]]) swap(x,y);
                    ans=max(ans,query(1,pathsize[pathid[x]],1,niv[x]-pathlvl[pathid[x]],pathdecalaj[pathid[x]],1));
                    x=pathtata[pathid[x]];
                }
            }
            cout << ans << '\n';
        }
    }
}