Cod sursa(job #2242632)

Utilizator LucaSeriSeritan Luca LucaSeri Data 19 septembrie 2018 08:59:26
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.59 kb
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

ifstream f("heavypath.in");
ofstream g("heavypath.out");

const int Max = 100010;

vector <int> lant[Max];
vector <int> Aint[Max];
vector <int> graf[Max];

int lantdenod[Max], v[Max], nivel[Max], tata[Max], sub[Max], poz[Max], lanturi = 0;

void build_aint(int lantisor, int node, int st, int dr){
    if(st == dr){
        Aint[lantisor][node] = v[lant[lantisor][st]];
        return;
    }
    int mij = st+dr>>1;
    build_aint(lantisor, node<<1, st, mij);
    build_aint(lantisor, node<<1|1, mij+1, dr);
    Aint[lantisor][node] = max(Aint[lantisor][node<<1], Aint[lantisor][node<<1|1]);
}

void update(int lantisor, int node, int st, int dr, int poz, int val){
    if(st == dr){
        Aint[lantisor][node] = val;
        return;
    }
    int mij = st+dr>>1;
    if(poz <= mij) update(lantisor, node<<1, st, mij, poz, val);
    else update(lantisor, node<<1|1, mij+1, dr, poz, val);

    Aint[lantisor][node] = max(Aint[lantisor][node<<1], Aint[lantisor][node<<1|1]);
}
void dfs(int node, int boss, int lvl){
    nivel[node] = lvl;
    sub[node] = 1;
    for(int x : graf[node]){
        if(x != boss){
            tata[x] = node;
            dfs(x, node, lvl+1);
            sub[node] += sub[x];
        }
    }
    if(graf[node].size() == 1 && node != 1){
        ++lanturi;
        lant[lanturi].push_back(0);
        lant[lanturi].push_back(node);
        lantdenod[node] = lanturi;
        poz[node] = 1;
        return;
    }

    int best = 0;
    for(int x : graf[node]){
        if(x != boss && sub[x] > sub[best]){
            best = x;
        }
    }

    lantdenod[node] = lantdenod[best];
    lant[lantdenod[best]].push_back(node);
    poz[node] = lant[lantdenod[node]].size()-1;
}

int range_query(int lantisor, int node, int st, int dr, int a, int b){
    if(st >= a && dr <= b){
        return Aint[lantisor][node];
    }

    int mij = st+dr>>1, leftmax = -1, rightmax = -1;
    if(a <= mij) leftmax = range_query(lantisor, node<<1, st, mij, a, b);
    if(b > mij) rightmax = range_query(lantisor, node<<1|1, mij+1, dr, a, b);
    return max(leftmax, rightmax);
}
int ans(int x, int y){
    int best = -1;
    while(true){
        int lx = lantdenod[x];
        int ly = lantdenod[y];
        if(lx == ly){
            int a = min(poz[x], poz[y]);
            int b = max(poz[x], poz[y]);
            best = max(best, range_query(lx, 1, 1, lant[lx].size()-1, a, b));
            break;
        }

        if(nivel[lant[lx][1]] < nivel[lant[ly][1]])
            swap(x, y);

        lx = lantdenod[x];
        ly = lantdenod[y];

        best = max(best, range_query(lx, 1, 1, lant[lx].size()-1, 1, poz[x]));
        x = tata[lant[lx][1]];
    }
    return best;
}
int main(){
    int n, m;
    f >> n >> m;
    for(int i = 1; i <= n; ++i){
        f >> v[i];
    }
    for(int i = 1, a, b; i < n; ++i){
        f >> a >> b;
        graf[a].push_back(b);
        graf[b].push_back(a);
    }
    dfs(1, 0, 0);

    for(int i = 1; i <= lanturi; ++i){
        reverse(lant[i].begin()+1, lant[i].end());
        Aint[i].resize(lant[i].size()<<2);
        build_aint(i, 1, 1, lant[i].size()-1);
    }
    for(int i = 1; i <= n; ++i){
        poz[i] = lant[lantdenod[i]].size()-poz[i];
    }
    for(int i = 1; i <= m; ++i){
        int t, a, b;
        f >> t >> a >> b;
        if(t == 0){
            update(lantdenod[a], 1, 1, lant[lantdenod[a]].size()-1, poz[a], b);
        }
        else g << ans(a, b) << '\n';
    }
    return 0;
}