Cod sursa(job #2778996)

Utilizator MateiAruxandeiMateiStefan MateiAruxandei Data 2 octombrie 2021 14:42:47
Problema Heavy Path Decomposition Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.52 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];
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;
			lev[it] = lev[nod] + 1;
			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){
    int rez = 0;
    while(1){
        if(chain[x] == chain[y]){
            rez = max(rez, query(1, 1, sizeCh[chain[x]], min(label[x], label[y]), max(label[y], label[x]), chain[x]));
            break;
        }
        if(lev[chainparent[chain[x]]] < lev[chainparent[chain[y]]])
            swap(x, y);
        rez = max(rez, query(1, 1, sizeCh[chain[x]], label[x], sizeCh[chain[x]], chain[x]));
        x = chainparent[chain[x]];
    }
    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);
	}

	lev[1] = 1;
	dad[1] = -1;
	subarb(1);
	compute_chains(1);
	compute_labels(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
			cout << search(x, y) << '\n';
	}
    PA();
}