Mai intai trebuie sa te autentifici.

Cod sursa(job #2198976)

Utilizator SqueekDanielTodasca Daniel SqueekDaniel Data 25 aprilie 2018 23:54:02
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.45 kb
#include <bits/stdc++.h>
#define dimn 100005
#define dimm 100005
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 index[dimn];                        //index[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 index, int left, int right, int nod=1) {
    if(left == right) {
        tree[index][nod] = v[chain[index][left]];
        return;
    } int mij = (left+right)/2;
    init(index, left, mij, 2*nod);
    init(index, mij+1, right, 2*nod+1);
    tree[index][nod] = std::max(tree[index][2*nod], tree[index][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++)
            index[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 = index[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(index[x], index[y]), std::max(index[x], index[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], index[y], 0, chain[nchain[y]].size()-1);
        }
    }
}

int main()
{
    citire();
    rezolvare();

    return 0;
}