제출 #1347180

#제출 시각아이디문제언어결과실행 시간메모리
1347180model_codeFestivals in JOI Kingdom 3 (JOI26_festival)C++20
100 / 100
2218 ms333344 KiB
#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#include <vector>
using std::vector;
using std::pair;
#include <algorithm>
using std::sort;
using std::max;
using std::min;
using std::reverse;
#include <set>
using std::set;

typedef long long int ll;
typedef pair<ll, ll> P;

const ll INF = 1'000'000'000'009;

ll n, q;
ll a[300'000], b[300'000], c[300'000], d[300'000];

ll qt[300'000], qi[300'000], qx[300'000];

vector<P> g[300'000];


typedef struct {
	ll chl;
	ll chr;
	ll add;
} segnode;
ll operate (segnode f, ll x) {
	return min(max(x, f.chl), f.chr) + f.add;
}
const segnode unity = {0, INF, 0};

// merge of parent node (r) and child node (l)
segnode merge (segnode r, segnode l) {
	segnode res;

	ll cll = l.chl;
	ll clr = l.chr;
	ll crl = r.chl - l.add;
	ll crr = r.chr - l.add;

	res.add = l.add + r.add;

	ll ml, mr;
	if (clr < crl) {
		ml = mr = crl;
	} else if (crr < cll) {
		ml = mr = crr;
	} else {
		ml = max(cll, crl);
		mr = min(clr, crr);
	}
	res.chl = ml;
	res.chr = mr;

	return res;
}

const ll base = 1 << 19;
segnode seg[1 << 20];
void seg_init (void) {
	for (ll i = 0; i < base * 2; i++) {
		seg[i] = unity;
	}
}
void seg_set (ll v, segnode x) {
	seg[v += base] = x;
	while (v /= 2) {
		seg[v] = merge(seg[v * 2 + 0], seg[v * 2 + 1]);
	}
}
segnode seg_find (ll l, ll r) {
	segnode suml = unity, sumr = unity;
	for ((l += base), (r += base); l < r; (l /= 2), (r /= 2)) {
		if (l % 2) {
			suml = merge(suml, seg[l++]);
		}
		if (r % 2) {
			sumr = merge(seg[--r], sumr);
		}
	}
	return merge(suml, sumr);
}

ll subsize[300'000]; // size of subtree
ll par[300'000]; // parent node (par[0] = 0)
ll upedge[300'000]; // edge leading to parent (upedge[0] = -1)
ll size_dfs (ll v, ll p) {
	subsize[v] = 1;
	for (auto &[u, e] : g[v]) {
		if (u == p) continue;

		par[u] = v;
		upedge[u] = e;
		subsize[v] += size_dfs(u, v);
	}
	return subsize[v];
}
void size_init () {
	par[0] = 0;
	upedge[0] = -1;
	size_dfs(0, n);
}
ll hlpar[300'000]; // top vertex of HL component v belongs
ll hlbottom[300'000]; // bottom vertex of HL component v belongs
ll heavy[300'000]; // heavy child (-1 for leaf)
vector<ll> hleuler; // HL euler tour
ll vtohl[300'000]; // hleuler[vtohl[v]] == v
void hl_dfs (ll v, ll p) {
	hleuler.push_back(v);
	vtohl[v] = hleuler.size() - 1;

	heavy[v] = -1;
	ll heavysize = 0;

	for (auto &[u, e] : g[v]) {
		if (u == p) continue;

		if (subsize[u] > heavysize) {
			heavysize = subsize[u];
			heavy[v] = u;
		}
	}

	if (heavy[v] == -1) {
		hlbottom[v] = v;
		return;
	}
	hlpar[heavy[v]] = hlpar[v];
	hl_dfs(heavy[v], v);
	hlbottom[v] = hlbottom[heavy[v]];
	for (auto &[u, e] : g[v]) {
		if (u == p) continue;
		
		if (u == heavy[v]) continue;

		hlpar[u] = u;
		hl_dfs(u, v);
	}
}
void hl_init () {
	size_init();
	
	hlpar[0] = 0;
	hl_dfs(0, n);
}
vector<P> hl_divide (ll v) {
	vector<P> vec;

	while (true) {
		ll p = hlpar[v];
		vec.push_back({p, v});
		if (p == 0) break;
		v = par[p];
	}

	reverse(vec.begin(), vec.end());
	return vec;
}

typedef struct {
	int32_t l;
	int32_t r;
	int32_t p;
	int32_t val;
} sparsenode;
vector<sparsenode> sparseseg;
int32_t roots[300'000];
const ll DEPTH = 60;
int32_t sparse_newroot (void) {
	int32_t idx = sparseseg.size();
	sparseseg.push_back((sparsenode){-1,-1,idx,0});
	return idx;
}
int32_t sparse_newnode (int32_t p) {
	int32_t idx = sparseseg.size();
	sparseseg.push_back((sparsenode){-1,-1,p,0});
	return idx;
}
void sprase_init (ll n) {
	for (ll i = 0; i < n; i++) {
		roots[i] = sparse_newroot();
	}
}
ll sparse_select (int32_t r, int32_t k) {
	ll ans = 0;
	ll curr = r;
	int32_t kc = k;
	for (ll i = DEPTH - 1; i >= 0; i--) {
		bool isr;
		int32_t minus;
		if (sparseseg[curr].l == -1) {
			// right
			minus = 0;
			isr = true;
		} else if (sparseseg[curr].r == -1) {
			// left
			minus = 0;
			isr = false;
		} else {
			if (sparseseg[sparseseg[curr].l].val < kc) {
				minus = sparseseg[sparseseg[curr].l].val;
				isr = true;
			} else {
				minus = 0;
				isr = false;
			}
		}

		if (isr) {
			ans |= (1LL << i);

			kc -= minus;
			curr = sparseseg[curr].r;
		} else {
			ans |= 0;

			kc -= 0;
			curr = sparseseg[curr].l;
		}
	}
	return ans;
}
int32_t sparse_access (int32_t r, ll u) {
	int32_t curr = r;

	for (ll i = DEPTH - 1; i >= 0; i--) {
		if (u & (1LL << i)) {
			// right
			if (sparseseg[curr].r == -1) {
				sparseseg[curr].r = sparse_newnode(curr);
			}
			curr = sparseseg[curr].r;
		} else {
			// left
			if (sparseseg[curr].l == -1) {
				sparseseg[curr].l = sparse_newnode(curr);
			}
			curr = sparseseg[curr].l;
		}
	}
	return curr;
}
void addchild (ll v, ll u, int32_t x) {
	int32_t curr = sparse_access(roots[v], u);

	while (true) {
		sparseseg[curr].val += x;
		if (curr == roots[v]) break;
		curr = sparseseg[curr].p;
	}
}
ll find_kth (ll v, ll k) {
	if (k <= 0) {
		return 0;
	} else if (sparseseg[roots[v]].val < k) {
		return INF;
	} else {
		return sparse_select(roots[v], k);
	}
}

ll top_uproot[300'000];
segnode op_check (ll v) {
	
	ll upadd;
	if (heavy[v] == -1) {
		upadd = INF;
	} else {
		upadd = d[upedge[heavy[v]]];
	}
	ll downadd;
	if (v == 0) {
		downadd = INF;
	} else {
		downadd = d[upedge[v]];
	}


	ll ml, mr;
	ml = find_kth(v, c[v] - 1);
	mr = find_kth(v, c[v]);

	segnode sn_up;
	sn_up.add = upadd;
	sn_up.chl = ml - sn_up.add;
	sn_up.chr = mr - sn_up.add;
	seg_set(vtohl[v], sn_up);
	
	segnode sn_down;
	sn_down.add = downadd;
	sn_down.chl = ml - sn_down.add;
	sn_down.chr = mr - sn_down.add;
	seg_set(base - 1 - vtohl[v], sn_down);

	return sn_up;
}
ll uproot (ll root) {
	ll bottom = hlbottom[root];

	segnode op = seg_find(vtohl[root], vtohl[bottom] + 1);
	
	return operate(op, INF);
}
void segvalue_dfs (ll v, ll p) {
	if (heavy[v] != -1) {
		segvalue_dfs(heavy[v], v);
	}
	for (auto &[u, e] : g[v]) {
		if (u == p) continue;
		if (u == heavy[v]) continue;
		segvalue_dfs(u, v);
	}


	// postorder
	for (auto &[u, e] : g[v]) {
		if (u == p) continue;
		if (u == heavy[v]) continue;
		
		ll cval = top_uproot[u] + d[upedge[u]];
		addchild(v, cval, +1);
	}
	

	segnode sn = op_check(v);

	if (v == 0 || hlpar[v] == v) {
		top_uproot[v] = uproot(v);
	}
}
void segvalue_init () {
	sprase_init(n);

	segvalue_dfs(0, n);
}

void kth_replace (ll v, P pold, P pnew) {
	addchild(v, pold.first, -1);
	addchild(v, pnew.first, +1);
}
void climb_uproot (ll v) {
	ll curr = v;
	while (true) {
		ll p = hlpar[curr];
		ll pup = uproot(p);
		ll pval_old = top_uproot[p] + d[upedge[p]];
		top_uproot[p] = pup;
		ll pval_new = top_uproot[p] + d[upedge[p]];

		if (p == 0) break;

		kth_replace(par[p], {pval_old, p}, {pval_new, p});

		segnode newnode = op_check(par[p]);

		curr = par[p];
	}
}
void edge_change (ll e, ll x) {
	ll v = a[e], u = b[e];
	if (par[v] == u) {
		ll t = v;
		v = u;
		u = t;
	}

	// par[u] == v
	if (hlpar[u] == hlpar[v]) {
		d[e] = x;
	} else {
		ll cval_old = top_uproot[u] + d[e];
		d[e] = x;
		ll cval_new = top_uproot[u] + d[e];

		kth_replace(v, {cval_old, u}, {cval_new, u});
	}
	op_check(u);
	op_check(v);

	climb_uproot(v);

}
void vertex_change (ll v, ll x) {
	c[v] = x;
	segnode newnode = op_check(v);

	climb_uproot(v);
}

segnode revseg_find (ll l, ll r) {
	return seg_find(base - r, base - l);
}
ll stepdown (ll v, ll t) {
	ll tup = t + d[upedge[v]];

	vector<ll> addlist;
	addlist.push_back(tup);
	if (heavy[v] != -1) {
		addlist.push_back(uproot(heavy[v]) + d[upedge[heavy[v]]]);
	}

	for (ll x : addlist) {
		addchild(v, x, +1);
	}
	ll tans = find_kth(v, c[v]);
	for (ll x : addlist) {
		addchild(v, x, -1);
	}

	return tans;
}
ll ask (ll v) {
	ll t0 = uproot(0);
	vector<P> roads = hl_divide(v);

	ll t = t0;
	for (ll i = 0; i < roads.size(); i++) {
		ll l = vtohl[roads[i].first];
		ll r = vtohl[roads[i].second];

		ll curri = l;
		if (l + 1 <= r - 1) {
			segnode sn = revseg_find(l + 1, r - 1 + 1);
			t = operate(sn, t);
			curri = r - 1;
		}

		while (curri < r) {
			++curri;
			ll currv = hleuler[curri];
			t = stepdown(currv, t);
		}
		if (i + 1 < roads.size()) {
			t = stepdown(roads[i + 1].first, t);
		}
	}
	return t;
}

void solve () {
	seg_init();
	hl_init();

	segvalue_init();

	for (ll i = 0; i < q; i++) {
		if (qt[i] == 1) {
			// v c
			ll v = qi[i];

			vertex_change(v, qx[i]);
			c[v] = qx[i];
		} else if (qt[i] == 2) {
			// e d
			ll e = qi[i];

			edge_change(e, qx[i]);
		} else {
			// v ?

			ll ans = ask(qi[i]);
			if (ans >= INF) {
				ans = -1;
			}
			cout << ans << "\n";
		}
	}
}

int main (void) {
	cin.tie(nullptr);
	std::ios_base::sync_with_stdio(false);

	cin >> n;
	for (ll i = 0; i < n - 1; i++) {
		cin >> a[i] >> b[i] >> d[i];
		a[i]--;
		b[i]--;
		
		// rev
		a[i] = n - 1 - a[i];
		b[i] = n - 1 - b[i];
	}
	for (ll i = 0; i < n; i++) {
		ll x;
		cin >> x;

		// rev
		c[n - 1 - i] = x;
	}
	cin >> q;
	for (ll i = 0; i < q; i++) {
		cin >> qt[i];
		if (qt[i] == 1 || qt[i] == 2) {
			cin >> qi[i] >> qx[i];
		} else {
			cin >> qi[i];
		}
		qi[i]--;

		// rev
		if (qt[i] == 1 || qt[i] == 3) {
			qi[i] = n - 1 - qi[i];
		}
	}

	for (ll i = 0; i < n - 1; i++) {
		g[a[i]].emplace_back(b[i], i);
		g[b[i]].emplace_back(a[i], i);
	}


	solve();
	return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...