Cod sursa(job #2412442)

Utilizator Dobricean_IoanDobricean Ionut Dobricean_Ioan Data 22 aprilie 2019 11:36:45
Problema Heavy Path Decomposition Scor 60
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.31 kb
#include <bits/stdc++.h>
#define dimn 100001
#define dimm 100001
const int global_root = 1;
 
std::ifstream f("heavypath.in");
std::ofstream g("heavypath.out");
                                        //vai de capul meu ce sunt cu declararile astea si ce am ajuns sa fac cu viata mea
int N, Q;
int parent[dimn];
int v[dimn], nivel[dimn];
int nc, nchain[dimn], gr[dimn];
int ord[dimn];                        //ord[i] - pozitia elementului i in lant
std::list <int> adj[dimn];
std::vector <int> chain[dimn], tree[dimn];
 
void dfs(int start = global_root, int level = 1) {
    nivel[start] = level;
    bool leaf = true;
    int nod = 0;
 
    gr[start] = 1;
    for(auto vec:adj[start])
        if(!nivel[vec]) {
            dfs(vec, level+1);
            parent[vec] = start;
            leaf = false;
 
            if(gr[vec] > gr[nod]) nod = vec;
            gr[start] += gr[vec];
        }
 
    if(leaf) nchain[start] = ++nc;
    else nchain[start] = nchain[nod];
    chain[nchain[start]].push_back(start);
}
 
void init(int ord, int left, int right, int nod=1) {
    if(left == right) {
        tree[ord][nod] = v[chain[ord][left]];
        return;
    } int mij = (left+right)/2;
    init(ord, left, mij, 2*nod);
    init(ord, mij+1, right, 2*nod+1);
    tree[ord][nod] = std::max(tree[ord][2*nod], tree[ord][2*nod+1]);
}
void arbore() {
    for (int i=1, j; i<=nc; i++) {
        std::reverse(chain[i].begin(), chain[i].end());
        for (j=0; j<chain[i].size(); j++)
            ord[chain[i][j]] = j;
        tree[i].resize(4*chain[i].size()+5);
        init(i, 0, chain[i].size()-1);
    }
}
 
void update(int ntree, int pos, int left, int right, int nod=1) {
    if(left==right) {
        tree[ntree][nod] = v[chain[ntree][left]];
        return;
    } int mij = (left+right)/2;
    if(pos<=mij) update(ntree, pos, left, mij, 2*nod);
    else update(ntree, pos, mij+1, right, 2*nod+1);
 
    tree[ntree][nod] = std::max(tree[ntree][2*nod], tree[ntree][2*nod+1]);
}
int max_interval(int ntree, int s, int d, int left, int right, int nod=1) {
    if(s<=left && right<=d) return tree[ntree][nod];
    int mij = (left+right)/2;
 
    int max = -2e9;
    if(s<=mij) max = max_interval(ntree, s, d, left, mij, 2*nod);
    if(mij<d) max = std::max(max, max_interval(ntree, s, d, mij+1, right, 2*nod+1));
    return max;
}
 
int query(int y, int x) {
    int res = INT_MIN;
    int a, b;
 
    while(nchain[x] != nchain[y]) {
        if(nivel[chain[nchain[x]][0]] < nivel[chain[nchain[y]][0]])		
            std::swap(x, y);
        a = 0; b = ord[x];
        res = std::max(res, max_interval(nchain[x], a, b, 0, chain[nchain[x]].size()-1));
        x = parent[chain[nchain[x]][0]];
    }
    return std::max(res, max_interval(nchain[x], std::min(ord[x], ord[y]), std::max(ord[x], ord[y]), 0, chain[nchain[x]].size()-1));
}
 
void citire() {
    f >> N >> Q;
    for (int i=0; i<N; i++)
        f >> v[i+1], parent[i+1] = i+1;
    for (int i=0, y, x; i<N-1; i++) {
        f >> y >> x;
        adj[y].push_back(x);
        adj[x].push_back(y);
    }
}
void rezolvare() {
    dfs();
    arbore();
    for (int i=0, t, y, x; i<Q; i++) {
        f >> t >> y >> x;
        if(t) g << query(y, x) << "\n";
        else {
            v[y] = x;
            update(nchain[y], ord[y], 0, chain[nchain[y]].size()-1);
        }
    }
}
 
int main()
{
    citire();
    rezolvare();
 
    return 0;
}