1828F - Two Centroids - CodeForces Solution


dfs and similar *2800

Please click on ads to support us..

C++ Code:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define pb push_back
#define all(x) (x).begin(), (x).end()

const int N = 5e5;

int n, p[N + 1], big[N + 1], top[N + 1] = {0, 1}, tin[N + 1], tout[N + 1], tick, sm[N];
vector<int> g[N + 1];

void upd_plus(int i, int x){
	for(; i < n; i |= i + 1) sm[i] += x;
}

int get(int r){
	r++;
	int res = 0;
	for(; r; r &= r + 1) res += sm[--r];
	return res;
}

int calc(int v = 1){
	int res = 1;
	pair<int, int> mx = {0, 0};
	for(int to: g[v]){
		int temp = calc(to);
		res += temp;
		mx = max(mx, {temp, to});
	}
	big[v] = mx.second;
	vector<int> temp;
	for(int to: g[v]){
		if(to != big[v]) temp.pb(to);
	}
	g[v] = temp;
	return res;
}

void dfs(int v = 1){
	tin[v] = tick++;
	if(big[v]){
		top[big[v]] = top[v];
		dfs(big[v]);
	}
	for(int to: g[v]){
		top[to] = to;
		dfs(to);
	}
	tout[v] = tick;
}

void upd(int v){
	while(v){
		upd_plus(tin[top[v]], 1);
		upd_plus(tin[v] + 1, -1);
		v = p[top[v]];
	}
}

bool anc(int u, int v){
	return tin[u] <= tin[v] && tout[v] <= tout[u];
}

int get_child(int u, int v){
	assert(1 <= u);
	assert(u <= n);
	if(!anc(v, u)) cout << "v = " << v << " u = " << u << endl;
	assert(anc(v, u));
	if(top[u] == top[v]) return big[v];
	u = top[u];
	if(p[u] == v) return u;
	return get_child(p[u], v);
}

void solve(){
	cin >> n;
	for(int i = 2; i <= n; i++){
		cin >> p[i];
		g[p[i]].pb(i);
	}
	calc();
	dfs();
	upd(1);
	upd(2);
	cout << "0 ";
	int c = 1, v = 2;
	for(int i = 3; i <= n; i++){
		upd(i);
		if(p[c] == v){
			if(!anc(c, i)){
				if(get(tin[c]) << 1 < i) swap(c, v);
			}
			else{
				int to = get_child(i, c);
				if(get(tin[to]) << 1 > i){
					v = c;
					c = to;
				}
				else if(get(tin[to]) > i - get(tin[c])) v = to;
			}
		}
		else{
			if(anc(v, i)){
				if(get(tin[v]) << 1 > i) swap(c, v);
			}
			else if(anc(c, i)){
				int to = get_child(i, c);
				if(get(tin[to]) << 1 > i){
					v = c;
					c = to;
				}
				else if(get(tin[to]) > get(tin[v])) v = to;
			}
			else{
				if(i > get(tin[c]) << 1){
					v = c;
					c = p[v];
				}
				else if(i - get(tin[c]) > get(tin[v])) v = p[c];
			}
		}
		if(p[c] == v) cout << (get(tin[c]) << 1) - i << ' ';
		else cout << i - (get(tin[v]) << 1) << ' ';
	}
	cout << '\n';
	tick = 0;
	for(int i = 0; i < n; i++) sm[i] = 0;
	for(int i = 1; i <= n; i++) g[i].clear();
}

main(){
	ios_base :: sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int T = 1;
	cin >> T;
	while(T--) solve();
}


Comments

Submit
0 Comments
More Questions

1717B - Madoka and Underground Competitions
61B - Hard Work
959B - Mahmoud and Ehab and the message
802G - Fake News (easy)
1717C - Madoka and Formal Statement
420A - Start Up
1031A - Golden Plate
1559C - Mocha and Hiking
427B - Prison Transfer
330A - Cakeminator
426A - Sereja and Mugs
363A - Soroban
1585C - Minimize Distance
1506E - Restoring the Permutation
1539A - Contest Start
363D - Renting Bikes
1198D - Rectangle Painting 1
1023B - Pair of Toys
1725A - Accumulation of Dominoes
1675E - Replace With the Previous Minimize
839A - Arya and Bran
16B - Burglar and Matches
1625B - Elementary Particles
1725G - Garage
1725B - Basketball Together
735A - Ostap and Grasshopper
1183B - Equalize Prices
1481A - Space Navigation
1437B - Reverse Binary Strings
1362B - Johnny and His Hobbies