Cod sursa(job #2530275)

Utilizator Bulboaca_EugenBulboaca Alexandru Eugen Bulboaca_Eugen Data 24 ianuarie 2020 16:37:05
Problema Heavy Path Decomposition Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.36 kb
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 50;
const int INF = 1e8;
const int LOGMAX = 20 + 4;
ifstream fin("heavypath.in");
ofstream fout("heavypath.out");
vector <int> g[MAXN], l[LOGMAX];
int lant[MAXN], sizee[MAXN], val[MAXN], father[MAXN], poz[MAXN];
bool seen[MAXN];
int aint[LOGMAX][4 * MAXN+ 2], cnt;
///lant[i] - lantul nodului i
///sizee[i] - marimea subarborelui de radacina i
///val[i] - valoarea nodului i
///father[i] - nodul de care se leaga lantul lui i
///poz[i] - pozitia in cadrul arborelui de intervale a lui i
///aint[i][j] - nodul j din arborele de intervale al lantului i
///l[i] - nodurile lantului i
int findd(int node){ ///stabilesc nodul in care se leaga lantul lui 'node' de graf
    if(lant[node] != lant[father[node]]) return father[node];
    return findd(father[node]);
}
void dfs(int node, int papa){ ///calculez marimea subarborelui fiecaruia
    if(!node) return ;
    sizee[node] = 1;
    for(auto x : g[node]) {
        if(x != papa) {
            dfs(x, node);
            sizee[node] = sizee[x] + 1;
        }
    }
}
void dfs2(int node){ ///creez lanturile adaugand greedy fiul cu size maxim
    if(seen[node]) return ;
    seen[node] = true;
    l[cnt].push_back(node);
    lant[node] = cnt;
    int maxim = 0, fiu = 0;
    for(auto x : g[node]){
        if(sizee[x] > maxim and !seen[x])
            maxim = sizee[x], fiu = x;
    }
    if(fiu ) dfs2(fiu);
}
/// arborii de intervale pe lanturi
void update(int p, int pos, int st, int dr, int l, int valoare){
    if(st == dr) {
        aint[l][p] = valoare;
        return;
    }
    int m = (st + dr ) / 2;
    if(pos > m) update(2 * p + 1, pos, m + 1, dr, l, valoare);
    else update(2 * p , pos, st, m, l, valoare);
    aint[l][p] = max(aint[l][2 * p], aint[l][2 * p + 1]);
}
int rasp;
void query(int p, int left, int right, int st, int dr, int l){
    if(left >= st and right <= dr) {
        rasp = max(rasp, aint[l][p]);
        return ;
    }
    int m = (left + right) / 2;
    if(dr > m) query(2 * p + 1, m + 1, right, st, dr, l);
    if(st <= m) query(2 * p, left, m, st, dr, l);
}
int main() /// HEAVY PATH DECOMPOSITION
{
    ios::sync_with_stdio(false);
    fin.tie(0); fout.tie(0);
    int n, m ; fin >> n >> m;
    for(int i = 1; i <= n; ++i)
        fin >> val[i];
    for(int i = 1; i < n; ++i){
        int x, y; fin >> x >> y;
        g[x].push_back(y);
        g[y].push_back(x);
        father[y] = x;
    }
    dfs(1, 0);
    for(int i = 1; i <= n; ++i)
        if(!seen[i]) ++cnt, dfs2(i);
    for(int i = 1; i <= cnt; ++i)
        for(int j = 0; j <= l[i].size() - 1; ++j)
            poz[l[i][j]] = j + 1;
    for(int i = 1; i <= n; ++i){
        father[i] = findd(i);
        update(1, poz[i], 1, l[lant[i]].size(), lant[i], val[i]);
    }
    for(int i = 1; i <= m; ++i){
        int type, x , y;
        fin >> type >> x >> y;
        if(type){
            rasp = 0;
            if(lant[x] == 1) swap(x, y);
            while(lant[x] != lant[y]){
                query(1, 1, l[lant[x]].size(), 1, poz[x], lant[x]);
                x = father[x];
            }
            query(1, 1, l[lant[x]].size(), min(poz[x], poz[y]), max(poz[y], poz[x]),lant[x]);
            fout << rasp << '\n';
        }
        else update(1, poz[x], 1, l[lant[x]].size(), lant[x], y);
    }
    return 0;
}