Cod sursa(job #2553812)

Utilizator bigmixerVictor Purice bigmixer Data 22 februarie 2020 12:06:23
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.09 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 modp=1999999973;

int n,m,val[100005],niv[100005],sub[100005],nrLight,pathid[100005];
int pathsize[100005],tata[100005],pathlvl[100005],tree[400005],pathdecalaj[100005];
bitset<100005>viz;
vector<int>path[100005],nod[100005];

void DFS(int s){
    viz[s]=1;
    sub[s]=1;
    int frunza=1,heavyN=-1;
    for(auto it:nod[s]){
        if(viz[it]==1) continue;
        niv[it] = niv[s]+1;
        frunza = 0;
        DFS(it);
        sub[s]+=sub[it];
        if(heavyN==-1) heavyN=it;
        else{
            if(sub[it]>sub[heavyN]) heavyN=it;
        }
    }
    if(frunza==1){
        ++nrLight;
        pathid[s]=nrLight;
        pathsize[s]=1;
        path[nrLight].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;
        tata[pathid[it]]=s;
        pathlvl[pathid[it]]=niv[s];
    }
    return;
}

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

void create_paths(){
    niv[1]=1;
    DFS(1);
    for(int i=1;i<=nrLight;i++){
        reverse(all(path[i]));
        if(i>1){
            pathdecalaj[i]=pathdecalaj[i-1]+4*pathsize[i-1];
        }
        build(1,pathsize[i],pathdecalaj[i],i,1);
    }
}

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

int query(int l,int r,int le,int re,int decalaj,int nod){
    if(le>r || re<l) return 0;
    else if(l>=le && r<=re){
        return tree[nod+decalaj];
    }
    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(){
    ifstream cin("heavypath.in");
    ofstream cout("heavypath.out");
    ios_base::sync_with_stdio(false);cin.tie(0);cerr.tie(0);cout.tie(0);
    srand(chrono::steady_clock::now().time_since_epoch().count());
    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);
    }
    cout << "CHECK" << '\n';
    create_paths();
    for(int i=1;i<=m;i++){
        int t,x,y;
        cin >> t >> x >> y;
        if(t==0){
            update(1,pathsize[pathid[x]],y,niv[x]-pathlvl[tata[pathid[x]]],pathdecalaj[pathid[x]],1);
        }
        else{
            int ans=0;
            while(true==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;
                }
                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=max(x,tata[pathid[x]]);
            }
            cout << ans << '\n';
        }
    }
}