Submission #428101

#TimeUsernameProblemLanguageResultExecution timeMemory
428101milleniumEeeeCapital City (JOI20_capital_city)C++17
11 / 100
1507 ms32592 KiB
#include <bits/stdc++.h>
#define fr first
#define sc second
#define pii pair<int, int>
#define pb push_back
#define szof(s) (int)s.size()
#define all(s) s.begin(), s.end()
#define fastInp ios_base::sync_with_stdio(0); cin.tie(0);
#define ll long long
template<class T>void chmax(T &a, T b){if (a < b)a = b;}
template<class T>void chmin(T &a, T b){if (b < a)a = b;}

using namespace std;

const int MAXN  = (int)2e5 + 5;
const int INF = 1e9;
const int L = 20;

int n, k;
vector <int> g[MAXN];
int c[MAXN];

int pr[MAXN][L + 1];
int tin[MAXN], tout[MAXN], tiktak = 0;

set <int> colors;
vector <int> color_comp[MAXN];


void precalc(int v, int par) {
	tin[v] = ++tiktak;
	pr[v][0] = par;
	for (int lv = 1; lv <= L; lv++) {
		pr[v][lv] = pr[pr[v][lv - 1]][lv - 1];
	}
	for (int to : g[v]) {
		if (to != par) {
			precalc(to, v);
		}
	}
	tout[v] = tiktak;
}

bool father(int a, int b) {
	return tin[a] <= tin[b] && tout[b] <= tout[a];
}

int get_lca(int a, int b) {
	if (father(a, b)) {
		return a;
	}
	if (father(b, a)) {
		return b;
	}
	for (int lv = L; lv >= 0; lv--) {
		if (!father(pr[a][lv], b)) {
			a = pr[a][lv];
		}
	}
	return pr[a][0];
}

int get_lca(vector <int> &vec) {
	int lca = vec[0];
	for (int i = 1; i < szof(vec); i++) {
		lca = get_lca(lca, vec[i]);
	}
	return lca;
}

int cur[MAXN];

int used[MAXN], used_id = 1;

void up_dfs(vector <int> &vec, int v, int root) {
	if (used[v] == used_id) {
		return;
	}
	used[v] = used_id;
	vec.pb(v);
	if (v != root) {
		up_dfs(vec, pr[v][0], root);		
	}	
}

void relax(vector <int> &comp) {
	used_id++;
	vector <int> res;
	int lca = get_lca(comp);
	for (int v : comp) {
		up_dfs(res, v, lca);
	}
	comp = res;
}

struct Subtask_1_2_Solve {
	Subtask_1_2_Solve () {
		
	}
	void run() {
		precalc(1, 1);
		int ans = INF;
		for (int cur_color : colors) {
			for (int i = 1; i <= n; i++) {
				cur[i] = c[i];
			}
			vector <int> comp;
			for (int i = 1; i <= n; i++) {
				if (c[i] == cur_color) {
					comp.pb(i);
				}
			}
			int cur_ans = 0;
			while (1) {
				relax(comp);
				bool ok = 1;
				set <int> new_colors;
				for (int v : comp) {
					ok &= (cur[v] == cur_color);
					if (cur[v] != cur_color) {
						new_colors.insert(cur[v]);
					}
				}
				if (ok) {
					break;
				}
				else {
					for (int el : new_colors) {
						cur_ans++;
						for (int v : color_comp[el]) {
							comp.pb(v);
							cur[v] = cur_color;
						}
					}
					continue;
				}
			}
			chmin(ans, cur_ans);
		}
		cout << ans << endl;
	}
};

struct Line_Solve {
	int l[MAXN], r[MAXN];	
	Line_Solve () {
		fill(l, l + MAXN, INF);
		fill(r, r + MAXN, -INF);
	}
	struct Point {
		int x, type;
		Point () {
			
		}
		Point (int x_, int type_) {
			x = x_, type = type_;
		}
		const bool operator < (const Point &other) {
			return x < other.x;
		}	 
	};
	void run() {
		vector <Point> vec;
		for (int i = 1; i <= n; i++) {
			chmin(l[c[i]], i);
			chmax(r[c[i]], i);
		}
		for (int i = 1; i <= k; i++) {
			vec.pb(Point(l[c[i]], 1));
			vec.pb(Point(r[c[i]], -1));
		}
		sort(all(vec));
		int cnt = 0;
		set <int> segment;
		int ans = INF;
		for (auto el : vec) {
			int x = el.x;
			int type = el.type;
			cnt += type;
			segment.insert(c[x]);
			if (cnt == 0) {
				chmin(ans, szof(segment) - 1);
				segment.clear();
			}
		}
		cout << ans << endl;
	}
};

signed main() {
	fastInp;
	cin >> n >> k;
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		g[u].pb(v);
		g[v].pb(u);
	}
	for (int i = 1; i <= n; i++) {
		cin >> c[i];
		colors.insert(c[i]);
		color_comp[c[i]].pb(i);
	}
	if (n <= 2000) {
		Subtask_1_2_Solve T;
		T.run();
		return 0;
	} else {
		Line_Solve T;
		T.run();
		return 0;
	}
}

/*
12 4
7 9
1 3
4 6
2 4
10 12
1 2
2 10
11 1
2 8
5 3
6 7
3
1
1
2
4
3
3
2
2
3
4
4

*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...