Cod sursa(job #2777789)

Utilizator MateiAruxandeiMateiStefan MateiAruxandei Data 24 septembrie 2021 16:11:07
Problema Heavy Path Decomposition Scor 40
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.98 kb

#include <bits/stdc++.h>
#define nozerous(x) (x & -x)
#define MOD 9901
#define EPS 0.00001
using namespace std;
using namespace std;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int INF = (1 << 30), NMAX(100005), VMAX(1000000);
using VI  = vector<int>;
using VVI = vector<VI>;
using VB  = vector<bool>;
using Point = array<int, 2>;
using ll = long long;
using cd = complex<double>;
const double PI = acos(-1);
void BUNA(const string& task = "")
{
    if (!task.empty())
        freopen((task + ".in").c_str(), "r", stdin),
                freopen((task + ".out").c_str(), "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
}
void PA()
{
    exit(0);
}

vector<int> G[NMAX];
int val[NMAX], lev[NMAX], sz[NMAX], dad[NMAX], chain[NMAX], heavy_child[NMAX], label[NMAX], sizeCh[NMAX], chainparent[NMAX], dp[NMAX][18];
int *Arb[NMAX];

inline void subarb(int nod){
	sz[nod] = 1;
	int maxx = -1;
	for(auto it: G[nod])
		if(!dad[it]){
			dad[it] = nod;
			subarb(it);
			sz[nod] += sz[it];
			if(maxx == -1)
				maxx = it;
			else if(sz[it] > sz[maxx])
				maxx = it;
		}
	heavy_child[nod] = maxx;
}
inline void compute_chains(int nod){
	if(heavy_child[nod] != -1)
		chain[heavy_child[nod]] = chain[nod];
	for(auto it: G[nod])
		if(it != dad[nod])
			compute_chains(it);
}
inline void compute_labels(int nod){
	for(auto it: G[nod])
		if(it != dad[nod]){
			if(chain[it] != chain[nod])
				chainparent[chain[it]] = nod;
			compute_labels(it);
		}
	label[nod] = ++sizeCh[chain[nod]];
}
inline void update(int nod, int st, int dr, int wh){
	if(st == dr)
		Arb[chain[wh]][nod] = val[wh];
	else {
		int mij = (st + dr) / 2;
		if(label[wh] <= mij)
			update(2 * nod, st, mij, wh);
		else update(2 * nod + 1, mij + 1, dr, wh);
		Arb[chain[wh]][nod] = max(Arb[chain[wh]][2 * nod], Arb[chain[wh]][2 * nod + 1]);
	}
}
int query(int nod, int st, int dr, int a, int b, int wh){
	if(a <= st && dr <= b)
		return Arb[wh][nod];
	else {
		int mij = (st + dr) / 2;
		int r1 = 0, r2 = 0;
		if(a <= mij)
			r1 = query(2 * nod, st, mij, a, b, wh);
		if(b > mij)
			r2 = query(2 * nod + 1, mij + 1, dr, a, b, wh);
		return max(r1, r2);
	}
}
inline int search(int x, int y){
	if(chain[x] == chain[y])
		return query(1, 1, sizeCh[chain[x]], label[x], label[y], chain[x]);
	else
		return max(search(chainparent[chain[x]], y), query(1, 1, sizeCh[chain[x]], label[x], sizeCh[chain[x]], chain[x]));
}
void dfs(int nod){
	for(int i = 1; i <= 17; ++i)
		if(dp[nod][i - 1] != -1)
			dp[nod][i] = dp[dp[nod][i - 1]][i - 1];
	for(auto it: G[nod])
		if(dad[nod] != it){
			lev[it] = lev[nod] + 1;
			dp[it][0] = nod;
			dfs(it);
		}
}
int lca(int x, int y){
	if(lev[x] < lev[y])
		swap(x, y);
	if(lev[x] != lev[y])
		for(int i = 17; i >= 0; --i)
			if(lev[x] - (1 << i) >= lev[y])
				x = dp[x][i];
	if(x == y)
		return x;
    int rez = 1;
	for(int i = 17; i >= 0; --i)
		if(dp[x][i] != -1 && dp[y][i] != -1 && dp[x][i] != dp[y][i])
			x = dp[x][i], y = dp[y][i];
        else if(dp[x][i] != -1)
            rez = dp[x][i];
	return rez;
}

int main()
{
    BUNA("heavypath");
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= n; ++i){
		cin >> val[i];
		chain[i] = i;
	}
	for(int i = 1; i < n; ++i){
		int x, y;
		cin >> x >> y;
		G[x].push_back(y);
		G[y].push_back(x);
	}

	dad[1] = -1;
	subarb(1);
	compute_chains(1);
	compute_labels(1);
	memset(dp, -1, sizeof(dp));
	dfs(1);

	set<int> s;
	for(int i = 1; i <= n; ++i)
		s.insert(chain[i]);
	for(auto it: s){
		Arb[it] = new int[4 * sizeCh[it] + 5];
		for(int i = 0; i <= 4 * sizeCh[it] + 2; ++i)
			Arb[it][i] = 0;
	}

	for(int i = 1; i <= n; ++i)
		update(1, 1, sizeCh[chain[i]], i);
	for(int i = 1; i <= m; ++i){
		int t, x, y;
		cin >> t >> x >> y;

		if(t == 0){
			val[x] = y;
			update(1, 1, sizeCh[chain[x]], x);
		}
		else {
			int z = lca(x, y);
			cout << max(search(x, z), search(y, z)) << '\n';
		}
	}
    PA();
}