一棵树,每次加一个节点,并且询问每次加后的树的直径
可以知道,每次加点后最多对树的直径的影响为 \(1\) 。而且有一个重要性质:加进的这个叶子如果能对答案产生贡献,那么这个叶子和原来直径一定有公共端点,所以我们求出每个状态下的 \(u和v和ans\) ,每次要么不更新,要么只更新一个节点。判断是否需要更新需要求 \(lca\) 所以可以先预处理,再加边。
#include <bits/stdc++.h> using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();} return x*f; } const int maxn=200030; int n,to[maxn],nxt[maxn],head[maxn],num; void add(int x,int y){num++;nxt[num]=head[x];to[num]=y;head[x]=num;} int dep[maxn],fa[maxn],son[maxn],siz[maxn],top[maxn],ans,u,v; void dfs_build(int p,int F) { siz[p]=1; fa[p]=F; dep[p]=dep[F]+1; for(int i=head[p];i;i=nxt[i]) { if(to[i]!=F) { dfs_build(to[i],p); siz[p]+=siz[to[i]]; if(siz[to[i]]>siz[son[p]]) son[p]=to[i]; } } } void dfs_create(int p,int tp) { top[p]=tp; if(son[p])dfs_create(son[p],tp); for(int i=head[p];i;i=nxt[i]) { if(to[i]!=son[p]&&to[i]!=fa[p]) dfs_create(to[i],to[i]); } } int Lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); return x; } bool judge(int u,int v) { int l=Lca(u,v); int ss=dep[u]+dep[v]-2*dep[l]; if(ss>ans) {ans=ss;return 1;} return 0; } int main() { n=read(); for(int i=2;i<=n;i++) { fa[i]=read(); add(fa[i],i); } dfs_build(1,1);dfs_create(1,1); u=v=1;ans=0; for(int i=2;i<=n;i++) { int ls=v; if(judge(u,i)) ls=i; if(judge(v,i)) { u=v; ls=i; } v=ls; printf("%d ",ans); } return 0; }