F. New Year Tree
F. New Year Tree
You are a programmer and you have a New Year Tree (not the traditional fur tree, though) — a tree of four vertices: one vertex of degree three (has number ), connected with three leaves (their numbers are from to ).
On the New Year, programmers usually have fun. You decided to have fun as well by adding vertices to the tree. One adding operation looks as follows:
First we choose some leaf of the tree with number .
Let's mark the number of vertices on the tree at this moment by variable , then two vertexes are added to the tree, their numbers are and , also you get new edges, one between vertices and and one between vertices and .
Your task is not just to model the process of adding vertices to the tree, but after each adding operation print the diameter of the current tree. Come on, let's solve the New Year problem!
Input
The first line contains integer — the number of operations. Each of the next lines contains integer — the operation of adding leaves to vertex . Variable represents the number of vertices in the current tree.
It is guaranteed that all given operations are correct.
Output
Print integers — the diameter of the current tree after each operation.
Examples
input
5
2
3
4
8
5
output
3
4
4
5
6
解题思路
不妨假设当前树中直径的两个端点为 和 ,现在要往 插入的两个儿子为 和 。显然我们只需考虑 和 是否为新的直径端点,由于 和 是等价的,这里我们只考虑 。
如果 不是新的直径端点,那么此时树中直径的端点仍是 和 。
否则 是新的直径端点,由树的直径的性质知道,直径的另外一个端点就是距离 最远的节点。由于 和 是 的儿子,等价于求距离 最远的节点。同样由性质知道,距离 最远的节点必定是任意直径中的其中一个端点。由于 和 不是距离 最远的节点,现在我们只需考虑在插入 和 前的树中,距离 最远的节点,也就是 或 。 和 中的较大者就是距离 最远的节点。
所以在插入 和 后,判断 能否作为新的直径节点的依据是 或 是否成立。例如, 成立的话,则令 。否则 成立则令 。否则直径端点仍是 和 。
为了求 ,我们需要用到 lca,因此在插入 和 的过程中动态维护倍增数组。
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e6 + 10;
int sz = 1;
int fa[N][20], dep[N];
void add(int u) {
int v = ++sz;
dep[v] = dep[u] + 1;
fa[v][0] = u;
for (int i = 1; i <= 19; i++) {
fa[v][i] = fa[fa[v][i - 1]][i - 1];
}
}
int lca(int a, int b) {
if (dep[a] < dep[b]) swap(a, b);
for (int i = 19; i >= 0; i--) {
if (dep[fa[a][i]] >= dep[b]) a = fa[a][i];
}
if (a == b) return a;
for (int i = 19; i >= 0; i--) {
if (fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i];
}
return fa[a][0];
}
int dist(int a, int b) {
return dep[a] + dep[b] - 2 * dep[lca(a, b)];
}
int main() {
int n;
scanf("%d", &n);
dep[1] = 1;
for (int i = 0; i < 3; i++) {
add(1);
}
int a = 2, b = 3;
while (n--) {
int x;
scanf("%d", &x);
add(x), add(x);
if (dist(a, sz - 1) > dist(a, b)) b = sz - 1;
else if (dist(b, sz - 1) > dist(a, b)) a = sz - 1;
printf("%d\n", dist(a, b));
}
return 0;
}
参考资料
Codeforces379 F. New Year Tree - DennyQi - 博客园:https://www.cnblogs.com/qixingzhi/p/9309102.html
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/18121628
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-04-08 用优先队列构造Huffman Tree及判断是否为最优编码的应用
2021-04-08 Huffman Codes