CodeForces 1266F Almost Same Distance

洛谷传送门

CF 传送门

好厉害。

特判 \(k = 1\)。首先经过观察,我们可以按照 \(k\) 的奇偶性讨论:

  1. \(k\) 为偶数,有一个中心点挂了若干条长度为 \(\frac{k}{2}\) 的链。
  2. \(k\) 为偶数,有两个中心点,两边挂了若干条长度为 \(\frac{k}{2}\) 的链;
  3. \(k\) 为奇数,有一个中心点挂了若干条长度为 \(\frac{k + 1}{2}\) 的链和至多一条长度为 \(\frac{k - 1}{2}\) 的链。

根据上面我们有 \(ans_k \ge ans_{k + 2}\)。最后取个后缀 \(\min\) 即可。接下来考虑如何处理这 \(3\) 种贡献。

我们可以把每个点的每棵子树挂的最长链预处理出来。然后按照这个长度扫描线。设当前点 \(u\) 出现次数为 \(b_u\)

对于第一种贡献,可以直接让 \(ans_{2i} \gets b_u\)

对于第二种贡献,我们要讨论 \(u\) 的所有邻居。维护 \(c_u\) 表示 \(u\) 的所有儿子的 \(b_u\) 的最大值。然后让 \(ans_{2i} \gets \max(b_u + c_u - 2, b_u + b_{fa_u} - 2)\) 即可。\(-2\) 是因为两棵子树互相重复贡献了。

对于第三种贡献,若 \(u\) 是在长度 \(i\) 中第一次出现,有 \(ans_{2i + 1} \gets b_u\),否则 \(ans_{2i - 1} \gets b_u\)

时间复杂度 \(O(n)\)

code
// Problem: F. Almost Same Distance
// Contest: Codeforces - Codeforces Global Round 6
// URL: https://codeforces.com/contest/1266/problem/F
// Memory Limit: 256 MB
// Time Limit: 5000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 1000100;

int n, f[maxn], g[maxn], h[maxn], a[maxn], b[maxn], c[maxn], fa[maxn];
bool vis[maxn];
vector<int> G[maxn], vc[maxn];

void dfs(int u, int fa) {
	for (int v : G[u]) {
		if (v == fa) {
			continue;
		}
		::fa[v] = u;
		dfs(v, u);
		vc[f[v] + 1].pb(u);
		if (f[v] + 1 > f[u]) {
			g[u] = f[u];
			f[u] = f[v] + 1;
		} else if (f[v] + 1 > g[u]) {
			g[u] = f[v] + 1;
		}
	}
}

void dfs2(int u, int fa) {
	for (int v : G[u]) {
		if (v == fa) {
			continue;
		}
		h[v] = max(h[u] + 1, f[v] + 1 == f[u] ? g[u] + 1 : f[u] + 1);
		vc[h[v]].pb(v);
		dfs2(v, u);
	}
}

void solve() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; ++i) {
		scanf("%d%d", &u, &v);
		G[u].pb(v);
		G[v].pb(u);
	}
	for (int i = 1; i <= n; ++i) {
		a[1] = max(a[1], (int)G[i].size() + 1);
	}
	dfs(1, -1);
	dfs2(1, -1);
	for (int i = n; i; --i) {
		for (int u : vc[i]) {
			++b[u];
			c[fa[u]] = max(c[fa[u]], b[u]);
			a[i * 2] = max({a[i * 2], b[u] + b[fa[u]] - 2, b[u] + c[u] - 2, b[u]});
			if (!vis[u]) {
				a[i * 2 + 1] = max(a[i * 2 + 1], b[u]);
			}
			a[i * 2 - 1] = max(a[i * 2 - 1], b[u]);
			vis[u] = 1;
		}
		for (int u : vc[i]) {
			vis[u] = 0;
		}
	}
	for (int i = n; i; --i) {
		a[i] = max({a[i], a[i + 2], 1});
	}
	for (int i = 1; i <= n; ++i) {
		printf("%d ", a[i]);
	}
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

posted @ 2024-01-15 18:36  zltzlt  阅读(18)  评论(0)    收藏  举报