Cod sursa(job #3294837)

Utilizator moldovan_robert_lolMoldovan Robert moldovan_robert_lol Data 29 aprilie 2025 12:59:37
Problema Heavy Path Decomposition Scor 80
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.21 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>
#include <functional>

std::ifstream fin("heavypath.in");
std::ofstream fout("heavypath.out");

int gs, q;
std::vector<std::vector<int>> adj_list;
int node_val[200005];
int depth[200005];
int sub_sz[200005];
int up[18][200005];
int heavy_child[200005];
bool heavy_parent[200005];
int label[200005];
int label_r[200005];
int tin[200005];
int tout[200005];
int top_of_chain[200005];
int segtree[800005];

void segtree_build(int node, int l, int r) {
    if (l==r) {
        segtree[node] = node_val[label_r[l]];
        return;
    }

    int m = (l+r)>>1;
    segtree_build(node<<1,l,m);
    segtree_build(node<<1|1,m+1,r);
    segtree[node] = std::max(segtree[node<<1], segtree[node<<1|1]);
}

void segtree_update(int node, int l, int r, int pos, int val) {
    if (l==r) {
        segtree[node] = val;
        return;
    }

    int m = (l+r)>>1;
    if (pos<=m) {
        segtree_update(node<<1,l,m,pos,val);
    }
    else {
        segtree_update(node<<1|1,m+1,r,pos,val);
    }
    segtree[node] = std::max(segtree[node<<1],segtree[node<<1|1]);
}

int segtree_query(int node, int l, int r, int st, int fi) {
    if (l>fi||r<st) {
        return -0x3f3f3f3f;
    }
    if (st<=l&&r<=fi) {
        return segtree[node];
    }

    int m = (l+r)>>1;
    return std::max(segtree_query(node<<1,l,m,st,fi), segtree_query(node<<1|1,m+1,r,st,fi));
}

int get_kth_ancestor(int node, int k) {
    while (k) {
        int l = 31-__builtin_clz(k);
        node = up[l][node];
        k ^= (1<<l);
    }
    return node;
}

int get_lca(int a, int b) {
    if (depth[a]>depth[b]) {
        std::swap(a,b);
    }
    
    b = get_kth_ancestor(b, depth[b]-depth[a]);
    for (int lvl = 17; a != b;) {
        while (lvl-1>=0&&up[lvl][a]==up[lvl][b]) {
            --lvl;
        }

        a = up[lvl][a];
        b = up[lvl][b];
    }

    return a;
}

void hld_update(int k, int v) {
    node_val[k] = v;
    segtree_update(1,1,gs,label[k],v);
}

int hld_query_subtree(int k) {
    return segtree_query(1,1,gs,tin[k],tout[k]);
}

int hld_query_path(int a, int b) {
    int lca = get_lca(a,b);
    int ret = -0x3f3f3f3f;
    for (auto k : {a, b}) {
        while (depth[k] >= depth[lca]) {
            if (heavy_parent[k]) {
                int r = label[k];
                int l = ((depth[top_of_chain[k]] >= depth[lca]) ? label[top_of_chain[k]] : label[lca]);
                ret = std::max(ret, segtree_query(1,1,gs,l,r));
                k = up[0][top_of_chain[k]];
            }
            else {
                ret = std::max(ret, node_val[k]);
                k = up[0][k];
            }
        }
    }

    return ret;
}

void read_data() {
    fin >> gs >> q;
    for (int i = 1; i <= gs; i++) {
        fin >> node_val[i];
    }
    
    adj_list.resize(gs+1);
    for (int i = 0, a, b; i < gs-1; i++) {
        fin >> a >> b;
        adj_list[a].emplace_back(b);
        adj_list[b].emplace_back(a);
    }
}

void dfs1(int k, int p) {
	depth[k] = depth[p] + 1;
	sub_sz[k] = 1;
	up[0][k] = p;
	for (int j = 1; j < 18; j++) {
		up[j][k] = up[j-1][up[j-1][k]];
	}

	for (const auto& i : adj_list[k]) {
		if (i!=p) {
			dfs1(i,k);
			sub_sz[k] += sub_sz[i];
			if (sub_sz[i] > sub_sz[heavy_child[k]]) {
				heavy_child[k] = i;
			}
		}
	}

	if (heavy_child[k]) {
		heavy_parent[heavy_child[k]] = 1;
	}
}

void dfs2(int k, int p, int& timer) {
	label[k] = tin[k] = tout[k] = ++timer;
	label_r[label[k]] = k;
	if (heavy_child[k]) {
		top_of_chain[heavy_child[k]] = top_of_chain[k];
		dfs2(heavy_child[k],k,timer);
	}

	for (const auto& i : adj_list[k]) {
		if (i!=p&&i!=heavy_child[k]) {
			top_of_chain[i] = i;
			dfs2(i,k,timer);
		}
	}

	tout[k] = timer;
}

void preprocess_tree() {
    dfs1(1,0);

    top_of_chain[1] = 1;
    int timer = 0;
    dfs2(1,0,timer);

    segtree_build(1,1,gs);
}

void answer_queries() {
    while (q--) {
        int op;
        fin >> op;

        if (op==0) {
            int k, v;
            fin >> k >> v;
            hld_update(k,v);
        }
        else {
            int a, b;
            fin >> a >> b;
            fout << hld_query_path(a,b) << "\n";
        }
    }
}

int main() {
    read_data();
    preprocess_tree();
    answer_queries();
}