Cod sursa(job #2781298)

Utilizator cyg_vladioanBirsan Vlad cyg_vladioan Data 8 octombrie 2021 23:30:59
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.3 kb
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cctype>
using namespace std;
const int NMAX = 100000;

char buffer[1 << 17];
int sz = (1 << 17) , crs = (1 << 17);
void get_int(int &x)
{
    for(; crs < sz && !isdigit(buffer[crs]) ; crs ++);
    if(crs == sz){
        fread(buffer, sz, 1, stdin);
        for(crs = 0; crs < sz && !isdigit(buffer[crs]); crs ++);
    }
    x = 0;
    for(; crs < sz && isdigit(buffer[crs]); crs ++)
        x = x * 10 + buffer[crs] - '0';
    if(crs == sz){
        fread(buffer, sz, 1, stdin);
        for(crs = 0; crs < sz && isdigit(buffer[crs]); crs ++)
            x = x * 10 + buffer[crs] - '0';
    }
}

vector <int> T[NMAX + 5];
vector <vector <int> > paths_list;
vector <int> emptyv;
int lvl[NMAX + 5], tata[NMAX + 5], path_end[NMAX + 5], ord;
int aint[4 * NMAX + 5], all_paths[NMAX + 5];
int v[NMAX + 5], n;
int noduri[NMAX + 5], path[NMAX + 5], nr_paths;


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

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

int poz;
void update(int nod, int st, int dr){
    if(st == dr)
        aint[nod] = v[all_paths[poz]];
    else{
        int med = (st + dr) / 2;
        if(poz <= med)
            update(nod<<1, st, med);
        else
            update((nod<<1)^1, med + 1, dr);
        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[x] > lvl[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;
    get_int(n);
    get_int(m);
    for(i = 1; i <= n; ++ i)
        get_int(v[i]);
    for(i = 1; i < n; ++ i){
        get_int(x);
        get_int(y);
        T[x].push_back(y);
        T[y].push_back(x);
    }

    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 ++){
        get_int(q);
        get_int(x);
        get_int(y);
        if(q == 0){
            v[x] = y;
            poz = pos[x];
            update(1, 1, n);
        }
        else
            printf("%d\n", solve(x, y));
    }
    return 0;
}