专栏文章

题解:AT_abc428_e [ABC428E] Farthest Vertex

AT_abc428_e题解参与者 1已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@minkfsva
此快照首次捕获于
2025/12/02 03:52
3 个月前
此快照最后确认于
2025/12/02 03:52
3 个月前
查看原文
给出一种比较暴力的解法吧。
首先我们发现每个点距离最大的点就是以那个点为根时的最大深度的点。
那么我们可以先暴力求出以一为根时,所有点的深度。
然后我们发现,如果原本以 uu 为根的点的深度,若要将它转为 uu 的儿子 vv 的点的深度,那么 vv 子树内的点的深度都减一,其余点的深度加一。
你可以想象一下,原本是 uu 为根,然后将他的儿子 vv 提根,相当于折一下,然后就是符合上述情况的。
然后又因为子树内的 dfndfn 序是连续的,于是我们可以第一遍遍历时先将以一为根所有点的深度和 dfndfn 求出来,然后用一个线段树维护每个点的深度值,第二遍遍历,每次要走到儿子的时候,就将深度值更新为以儿子为根时的深度值,然后答案就是以那个点为根时的最大深度值所在的最大点。
注意,要求的不是最大距离,而是其所在点,这里我在线段树上用了一个 pospos 维护。

code

CPP
#include <bits/stdc++.h>
#define pb push_back
using namespace std;

const int N = 5e5 + 10;

vector <int> g[N];

int n, cnt, dep[N], dfn[N], mxdfn[N], id[N], ans[N];

struct SegmentTree {
	int t[N << 2], pos[N << 2], tag[N << 2];
	
	#define ls (p << 1)
	#define rs (p << 1 | 1)
	#define mid ((l + r) >> 1)
	
	inline void pushup (int p) {
		t[p] = max (t[ls], t[rs]);
		if (t[ls] == t[rs]) pos[p] = max (pos[ls], pos[rs]);
		else pos[p] = (t[ls] > t[rs] ? pos[ls] : pos[rs]);
	}
	
	inline void pushdown (int p) {
		if (tag[p]) t[ls] += tag[p], t[rs] += tag[p], tag[ls] += tag[p], tag[rs] += tag[p], tag[p] = 0;
	}
	
	void build (int p, int l, int r) {
		if (l == r) return t[p] = dep[id[l]], pos[p] = id[l], void ();
		build (ls, l, mid), build (rs, mid + 1, r), pushup (p);
	}
	
	void update (int p, int l, int r, int L, int R, int k) {
		if (L > R) return; 
		if (L <= l and r <= R) return t[p] += k, tag[p] += k, void ();
		pushdown (p);
		if (L <= mid) update (ls, l, mid, L, R, k);
		if (R > mid) update (rs, mid + 1, r, L, R, k);
		pushup (p);
	}
} seg;

void dfs1 (int u, int fa) {
	dep[u] = dep[fa] + 1, dfn[u] = mxdfn[u] = ++cnt, id[cnt] = u;
	for (int v : g[u])
		if (v != fa) dfs1 (v, u), mxdfn[u] = max (mxdfn[u], mxdfn[v]);
}

void dfs2 (int u, int fa) {
	ans[u] = seg.pos[1];
	for (int v : g[u]) 
		if (v != fa) {
			seg.update (1, 1, n, dfn[v], mxdfn[v], -1);
			seg.update (1, 1, n, 1, dfn[v] - 1, 1);
			seg.update (1, 1, n, mxdfn[v] + 1, n, 1);
			dfs2 (v, u);
			seg.update (1, 1, n, dfn[v], mxdfn[v], 1);
			seg.update (1, 1, n, 1, dfn[v] - 1, -1);
			seg.update (1, 1, n, mxdfn[v] + 1, n, -1); 
		}
}

int main () {
	cin >> n;
	for (int i = 1, u, v; i < n; i++) cin >> u >> v, g[u].pb (v), g[v].pb (u); 
	dfs1 (1, 0), seg.build (1, 1, n), dfs2 (1, 0);
	for (int i = 1; i <= n; i++) cout << ans[i] << endl;
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...