题意
给定图:
每次在叶子结点加入两个点,并实时输出树的直径长度。
思路
每次增加两个点,直径至多变化一个点,长度最多加 1,所以对加入的点处理 lca,并且更新长度和点即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010;
int fa[30][N], dep[N];
void process(int u) {
for (int i = 1; i < 30; i++) {
fa[i][u] = fa[i - 1][fa[i - 1][u]];
}
}
int lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int j = 29; j >= 0; j--) {
if (dep[fa[j][u]] >= dep[v]) u = fa[j][u];
}
if (u == v) return u;
for (int j = 29; j >= 0; j--) {
if (fa[j][u] != fa[j][v]) {
u = fa[j][u];
v = fa[j][v];
}
}
return fa[0][u];
}
int dis(int u, int v) {
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int q;
cin >> q;
fa[0][2] = fa[0][3] = fa[0][4] = 1;
dep[2] = dep[3] = dep[4] = 1;
int a1 = 2, a2 = 3, res = 2, ver = 5;
for (int opt = 1; opt <= q; opt++) {
int x;
cin >> x;
fa[0][ver] = fa[0][ver + 1] = x;
dep[ver] = dep[ver + 1] = dep[x] + 1;
process(ver);
process(ver + 1);
int len1 = dis(a1, ver);
int len2 = dis(a2, ver);
int len3 = dis(a1, ver + 1);
int len4 = dis(a2, ver + 1);
if (len1 > res) {
res = len1;
a2 = ver;
}
else if (len2 > res) {
res = len2;
a1 = ver;
}
else if (len3 > res) {
res = len3;
a2 = ver + 1;
}
else if (len4 > res) {
res = len4;
a1 = ver + 1;
}
cout << res << '\n';
ver += 2;
}
return 0;
}
标签:dep,ver,int,res,Tree,a1,fa,New,CF379F
From: https://www.cnblogs.com/Yuan-Jiawei/p/18350399