Cod sursa(job #2781226)

Utilizator cyg_vladioanBirsan Vlad cyg_vladioan Data 8 octombrie 2021 19:26:54
Problema Heavy Path Decomposition Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.15 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int NMAX = 100000;
vector <int> T[NMAX + 5];

int first_ap[NMAX + 5], lvl[2 * NMAX + 5], t[2 * NMAX + 5], tata[NMAX + 5], path_end[NMAX + 5], ord;//path_end[i] = nivelul la care se termina poteca i
int v[NMAX + 5], n;

void dfs(int u, int l){
    int v;
    first_ap[u] = ++ ord;
    lvl[ord] = l;
    t[ord] = u;
    for(int i = 0; i < T[u].size(); i ++){
        v = T[u][i];
        if(!first_ap[v]){
          dfs(v, l + 1);
          tata[v] = u;
          lvl[++ ord] = l;
          t[ord] = u;
        }
    }
}

//Heavy Path Decomposition (HPD)
vector <vector <int> > paths_list;
vector <int> emptyv;
int noduri[NMAX + 5], viz[NMAX + 5], path[NMAX + 5], nr_paths;

void dfsHPD(int u){
    int v, i, nod = -1;
    viz[u] = 1;
    for(i = 0; i < T[u].size(); i ++){
        v = T[u][i];
        if(!viz[v]){
            dfsHPD(v);
            noduri[u] += noduri[v];
            if(nod == -1 || noduri[v] > noduri[nod])
                nod = v;
        }
    }
    noduri[u] ++;
    if(noduri[u] > 1){
        path[u] = path[nod];
        paths_list[path[nod]].push_back(u);
        for(i = 0; i < T[u].size(); i ++){
            v = T[u][i];
            if(v != tata[u] && v != nod)
                path_end[path[v]] = lvl[t[v]];
        }
    }
    else{
        path[u] = ++ nr_paths;
        paths_list.push_back(emptyv);
        paths_list[nr_paths].push_back(u);
    }
}

//AINT
int aint[4 * NMAX + 5], all_paths[NMAX + 5];

void build(int nod, int st, int dr){
    if(st == dr)
        aint[nod] = v[all_paths[st]];
    else
    {
        int med = (st + dr) / 2;
        build(nod<<1, st, med);
        build((nod << 1)^1, med + 1, dr);
        aint[nod] = max(aint[nod<<1], aint[(nod<<1)^1]);
    }
}

void update(int nod, int st, int dr, int poz){
    if(st == dr)
        aint[nod] = v[all_paths[poz]];
    else{
        int med = (st + dr) / 2;
        if(poz <= med)
            update(nod<<1, st, med, poz);
        else
            update((nod<<1)^1, med + 1, dr, poz);
        aint[nod] = max(aint[nod<<1], aint[(nod<<1)^1]);
    }
}

int qa, qb, sol;
void queryaint(int nod, int st, int dr){
    if(qa <= st && dr <= qb)
        sol = max(sol, aint[nod]);
    else{
       int med = (st + dr) / 2;
       if(qa <= med)
          queryaint(nod << 1, st, med);
       if(qb > med)
          queryaint((nod<<1)^1, med + 1, dr);
    }
}

int paths_starts[NMAX + 5], pos[NMAX + 5];//pos[i]-pozitia nodului i in all_paths; all_paths reprezinta reuniunea tuturor lanturilor

int solve(int x, int y){
    sol = 0;
    while(path[x] != path[y]){
        if(path_end[path[x]] >= path_end[path[y]]){
            qa = paths_starts[path[x]];
            qb = pos[x];
            queryaint(1, 1, n);
            x = tata[all_paths[paths_starts[path[x]]]];
        }
        else{
            qa = paths_starts[path[y]];
            qb = pos[y];
            queryaint(1, 1, n);
            y = tata[all_paths[paths_starts[path[y]]]];
        }
    }
    if(lvl[first_ap[x]] > lvl[first_ap[y]])
            swap(x, y);
    qa = pos[x];
    qb = pos[y];
    queryaint(1, 1, n);
    return sol;
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int m, i, j, x, y, q;
    scanf("%d%d", &n, &m);
    for(i = 1; i <= n; i ++)
        scanf("%d", &v[i]);
    for(i = 1; i < n; i ++){
        scanf("%d%d", &x, &y);
        T[x].push_back(y);
        T[y].push_back(x);
    }
    dfs(1, 0);

    paths_list.push_back(emptyv);
    dfsHPD(1);
    int k = 0;
    for(i = 1; i <= nr_paths; i ++){
        paths_starts[i] = k + 1;
        for(j = paths_list[i].size() - 1 ; j >= 0 ; j --){
            all_paths[++ k] = paths_list[i][j];
            pos[paths_list[i][j]] = k;
        }
    }
    build(1, 1, n);

    for(i = 1 ; i <= m ; i ++){
        scanf("%d%d%d", &q, &x, &y);
        if(q == 0){
            v[x] = y;
            update(1, 1, n, pos[x]);
        }
        else
            printf("%d\n", solve(x, y));
    }
    return 0;
}