Submission #1180802

#TimeUsernameProblemLanguageResultExecution timeMemory
1180802jbarejaUnique Cities (JOI19_ho_t5)C++20
100 / 100
353 ms53884 KiB
#include <bits/stdc++.h>

using namespace std;

struct SegTree {
	vector<int> values;
	int base;

	void Init(int n) {
		base = 1;
		while (base <= n) base *= 2;
		values.assign(base * 2, 0);
	}

	void Add(int l, int r, int val) {
		l += base - 1;
		r += base + 1;
		while (l/2 != r/2) {
			if (l % 2 == 0) values[l+1] += val;
			if (r % 2 != 0) values[r-1] += val;
			l /= 2, r /= 2;
		}
	}

	int Sum(int x) {
		x += base;
		int ans = 0;
		while (x) {
			ans += values[x];
			x /= 2;
		}
		return ans;
	}
};

struct CntUniques {
	int cnt_uniques = 0;
	vector<int> cnt_values;

	void Init(int n) {
		cnt_values.assign(n+1, 0);
	}

	void Insert(int x) {
		if (!cnt_values[x]) cnt_uniques++;
		cnt_values[x]++;
	}

	void Erase(int x) {
		cnt_values[x]--;
		if (!cnt_values[x]) cnt_uniques--;
	}

	int Uniques() {
		return cnt_uniques;
	}
};

int N; // liczba wierzchołków
int M; // maksymalny numer specjalności

vector<vector<int>> graph;
vector<int> speciality;

vector<int> depth;
vector<int> answer;
int max_depth = 0;
SegTree tree;
vector<int> height;
CntUniques U;

int dfs_farthest_from(int v, int p=0) {
	if (p == 0) depth[v] = 1;
	int ans = v;
	for (int u: graph[v]) if (u != p) {
		depth[u] = depth[v] + 1;
		max_depth = max(depth[u], max_depth);
		int temp = dfs_farthest_from(u, v);
		if (depth[temp] > depth[ans]) ans = temp;
	}
	return ans;
}

void dfs_subtree_height(int v, int p=0) {
	if (p == 0) depth[v] = 1;
	height[v] = 1;
	for (int u: graph[v]) if (u != p) {
		depth[u] = depth[v] + 1;
		dfs_subtree_height(u, v);
		height[v] = max(height[v], height[u] + 1);
	}
}

vector<int> path = { 0 };

void dfs_count_answer(int v, int p=0, int upper=0, int bottom=0) {
	path.push_back(v);
	vector<int> unlocked;
	for (int u: graph[v]) if (u != p) {
		int upper_border = max(0, depth[v]-height[u]);
		int bottom_border = depth[p];
		tree.Add(upper_border, bottom_border, 1);
	}
	if (depth[v] > 1) {
		tree.Add(upper, bottom, -1);
		for (int i=max(1,upper); i<upper+2 && i<depth[v]; i++) {
			if (tree.Sum(i) == 0) {
				unlocked.push_back(speciality[path[i]]);
				U.Insert(speciality[path[i]]);
			}
		}
	}
	answer[v] = max(answer[v], U.Uniques());
	for (int u: graph[v]) if (u != p) {
		int upper_border = max(0, depth[v]-height[u]);
		int bottom_border = depth[p];
		dfs_count_answer(u, v, upper_border, bottom_border);
	}

	path.pop_back();
	for (int u: graph[v]) if (u != p) {
		int upper_border = max(0, depth[v]-height[u]);
		int bottom_border = depth[p];
		tree.Add(upper_border, bottom_border, -1);
	}
	if (depth[v] > 1) {
		tree.Add(upper, bottom, 1);
		for (int i: unlocked) U.Erase(i);
	}
}

void count_from(int v_start) {
	dfs_subtree_height(v_start);
	depth[0] = 0;
	dfs_count_answer(v_start);
}

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

	cin >> N >> M;

	graph.assign(N+1, vector<int>());
	speciality.assign(N+1, 0);
	depth.assign(N+1, 0);
	answer.assign(N+1, 0);
	height.assign(N+1, 0);
	U.Init(M);

	for (int i=0; i<N-1; i++) {
		int A, B;
		cin >> A >> B;
		graph[A].push_back(B);
		graph[B].push_back(A);
	}

	for (int i=1; i<=N; i++) cin >> speciality[i];

	int vA = dfs_farthest_from(1);
	int vB = dfs_farthest_from(vA);

	tree.Init(max_depth + 1);

	count_from(vA);
	count_from(vB);

	for (int i=1; i<=N; i++) cout << answer[i] << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...