Cod sursa(job #2781186)

Utilizator cyg_vladioanBirsan Vlad cyg_vladioan Data 8 octombrie 2021 18:29:02
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.48 kb
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int NMAX = 1000;
vector <int> T[NMAX + 5];

//LCA
int first_ap[NMAX + 5], lvl[2 * NMAX + 5], t[2 * NMAX + 5], tata[NMAX + 5],ord;
int d[2 * NMAX + 5][14], log2[2 * NMAX + 5];
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;
        }
    }
}

void dinamica(){
    int i , j;
    for(i = 1; i <= ord; i ++)
        d[i][0] = i;
    for(j = 1; (1 << j) <= ord; j ++)
        for(i = 1; i <= ord - (1 << j) + 1; i ++)
            if(lvl[d[i][j - 1]] <= lvl[d[i + (1 << (j - 1))][j - 1]])
                d[i][j] = d[i][j - 1];
            else
                d[i][j] = d[i + (1 << (j - 1))][j - 1];
}

int query(int x, int y){
    int p = log2[y - x + 1] - 1;
    if(lvl[d[x][p]] <= lvl[d[y - (1 << p) + 1][p]])
        return t[d[x][p]];
    return t[d[y - (1 << p) + 1][p]];
}

//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);

    }
    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

void find_max(int x, int lca){
    while(path[x] != path[lca])
    {
        qa = paths_starts[path[x]];
        qb = pos[x];
        queryaint(1, 1, n);
        x = tata[all_paths[paths_starts[path[x]]]];
    }
    qa = pos[lca];
    qb = pos[x];
    queryaint(1, 1, n);
}

int solve(int x, int y){
  sol = 0;
  int lca = query(min(first_ap[x], first_ap[y]), max(first_ap[x], first_ap[y]));
  find_max(x, lca);
  find_max(y, lca);
  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);
    dinamica();
    for(i = 1; (1 << i) <= ord; i ++)
        log2[1 << i] = 1;
    for(i = 1; i <= ord; i ++)
        log2[i] += log2[i - 1];

    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;
}