Submission #1368454

#TimeUsernameProblemLanguageResultExecution timeMemory
1368454vlomaczkCollecting Stamps 5 (JOI26_stamps)C++20
100 / 100
2835 ms374620 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
typedef long long ll;
using namespace __gnu_pbds;
using namespace std;
#define ff first
#define ss second
#define pi pair<int, int>
#define pll pair<long long, long long>
#define vi vector<int>
#define vll vector<long long>
#define vpi vector<pair<int,int>>
#define vpll vector<pair<long long, long long>>
#define pb push_back
#define count_bits(x) __builtin_popcountll((x))
#define all(x) (x).begin(),(x).end()
#define sz(x) (ll)(x).size()
#define forall(it,x) for(auto& it:(x))
#define mp make_pair
pi operator+(pi a, pi b) { return mp(a.ff+b.ff, a.ss+b.ss); }
pi operator-(pi a, pi b) { return mp(a.ff-b.ff, a.ss-b.ss); }
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

int D;
int M = 400'010;
vector<vector<int>> g(M);
vector<int> par(M), sajz(M), is_off(M), par_idx(M), dist(M), T(M), parent(M), old_T(M);
vector<vector<int>> ans(M), anst0(M);
vector<vector<vector<int>>> st_ans(M), st_anst0(M);

void sajz_dfs(int v, int p) {
	parent[v] = p;
	sajz[v] = 1;
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		sajz_dfs(u,v);
		sajz[v] += sajz[u];
	}
}

ll find_centroid(ll v, ll ts) {
	for(auto u : g[v]) {
		if(is_off[u]) continue;
		if(u==parent[v]) {
			if(ts-sajz[v] > ts/2) return find_centroid(u,ts);
		} else {
			if(sajz[u] > ts/2) return find_centroid(u,ts);
		}
	}
	return v;
}

vector<int> zb;
void zb_dfs(int v, int p) {
	zb.pb(v);
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		zb_dfs(u,v);
	}
}

void dist_dfs(int v, int p) {
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		dist[u] = dist[v] + 1;
		dist_dfs(u,v);
	}
}

void newT_dfs(int v, int p) {
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		T[u] = min(T[u], T[v] + 1);
		newT_dfs(u,v);
	}
}

void zeroT_dfs(int v, int p) {
	T[v] = 0;
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		zeroT_dfs(u,v);
	}
}

void oldT_dfs(int v, int p) {
	T[v] = old_T[v];
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		oldT_dfs(u,v);
	}
}

vector<vector<int>> get_dist(M), is_full(M);

void full_dfs(int v, int p, int ctr, int d, int best) {
	best = min(best, d + T[v]);
	int val = 0;
	if(d >= best) val = 1;
	is_full[v].pb(val);
	get_dist[v].pb(d);
	for(auto u : g[v]) {
		if(u==p || is_off[u]) continue;
		full_dfs(u,v,ctr,d+1,best);
	}
}


int ctd(int v) {
	sajz_dfs(v, v);
	v = find_centroid(v, sajz[v]);

	full_dfs(v,v,v,0,T[v]);
	
	dist[v] = 0;
	dist_dfs(v,v);

	newT_dfs(v,v);

	while(zb.size()) zb.pop_back();
	zb_dfs(v,v);
	int max_dist = 0;
	for(auto x : zb) max_dist = max(max_dist, dist[x]);
	ans[v].assign(max_dist + 1, 0);
	anst0[v].assign(max_dist + 1, 0);
	for(auto x : zb) {
		int L = T[x] - dist[x];
		int R = D - dist[x];
		if(L < 0) L=0;
		if(R > max_dist) R=max_dist;

		if(R >= 0) {
			anst0[v][0]++;
			if(R + 1 <= max_dist) anst0[v][R+1]--;
		}

		if(L > R) continue;
		ans[v][L]++;
		if(R + 1 <= max_dist) ans[v][R+1]--;
	}
	for(int i=1; i<=max_dist; ++i) ans[v][i] += ans[v][i-1];
	for(int i=1; i<=max_dist; ++i) anst0[v][i] += anst0[v][i-1];

	for(auto u : g[v]) {
		if(is_off[u]) continue;
		while(zb.size()) zb.pop_back();
		zb_dfs(u, v);
		st_ans[v].pb({});
		st_anst0[v].pb({});

		int max_d = 0;
		for(auto x : zb) max_d = max(max_d, dist[x]);
		st_ans[v].back().assign(max_d+1, 0);
		st_anst0[v].back().assign(max_d+1, 0);
		for(auto x : zb) {
			int L = T[x] - dist[x];
			int R = D - dist[x];
			if(L < 0) L=0;
			if(R > max_d) R=max_d;

			if(R >= 0) {
				st_anst0[v].back()[0]++;
				if(R + 1 <= max_d) st_anst0[v].back()[R+1]--;
			}

			if(L > R) continue;
			st_ans[v].back()[L]++;
			if(R + 1 <= max_d) st_ans[v].back()[R+1]--;
		}
		for(int i=1; i<=max_d; ++i) st_ans[v].back()[i] += st_ans[v].back()[i-1];
		for(int i=1; i<=max_d; ++i) st_anst0[v].back()[i] += st_anst0[v].back()[i-1];
	}

	oldT_dfs(v,v);

	is_off[v] = 1;
	int idx = 0;
	for(auto u : g[v]) {
		if(is_off[u]) continue;
		int ctr = ctd(u);
		par[ctr] = v;
		par_idx[ctr] = idx;
		++idx;
	}
	return v;
}

signed main() {
	ios_base::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);

	int n;
	cin >> n >> D;
	for(int i=1; i<=n; ++i) cin >> T[i];
	old_T = T;
	for(int i=1; i<n; ++i) {
		int a, b;
		cin >> a >> b;
		g[a].pb(b);
		g[b].pb(a);
	}
	int ctr = ctd(1);
	par[ctr] = -1;

	for(int i=1; i<=n; ++i) {
		int v = i;
		int idx = -1;
		ll res = 0;
		while(v != -1) {
			int my_d = get_dist[i].back();
			get_dist[i].pop_back();
			int isf = is_full[i].back();
			is_full[i].pop_back();
			if(my_d <= D) {
				if(!isf) {
					res += ans[v][my_d];
					if(idx != -1) res -= st_ans[v][idx][my_d];
				} else {
					res += anst0[v][my_d];
					if(idx != -1) res -= st_anst0[v][idx][my_d];
				}
			}
			idx = par_idx[v];
			v = par[v];
		}
		cout << res << "\n";
	}

	return 0;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...