考虑在加节点时维护 直径 , 和距离 直径 最远的点 , 在询问时直接将 链 截到直径端点即可 .
在加入一个节点 时, 这个节点可能会替代 , 或者替代 ,
注意在计算 离直径距离 时需要留心 是否在 直径lca 下面, 计算方式不同 .
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 2e5 + 10;
int N;
int u;
int v;
int s;
int Len;
int dep[maxn];
int Fk[maxn][20];
int Lca(int x, int y){
if(dep[x] < dep[y]) std::swap(x, y);
for(reg int i = 19; i >= 0; i --)
if(dep[Fk[x][i]] >= dep[y]) x = Fk[x][i];
if(x == y) return x;
for(reg int i = 19; i >= 0; i --)
if(Fk[x][i] != Fk[y][i]) x = Fk[x][i], y = Fk[y][i];
return Fk[x][0];
}
int Dis(const int &x, const int &y){ return dep[x] + dep[y] - (dep[Lca(x, y)] << 1); }
int Dis_2(int x){
int lca = Lca(u, v);
if(Lca(lca, x) == lca) return std::min(Dis(Lca(x, u), x), Dis(Lca(x, v), x));
return Dis(lca, x);
}
void Add(int fa, int x){
Fk[x][0] = fa; dep[x] = dep[fa] + 1;
for(reg int i = 1; i <= 19; i ++) Fk[x][i] = Fk[Fk[x][i-1]][i-1];
if(Dis(x, u) < Dis(x, v)) std::swap(u, v);
int t = Dis(x, u);
if(Len < t) Len = t, std::swap(x, v);
if(Dis_2(x) > Dis_2(s)) s = x;
}
int main(){
read(); N = read(); dep[1] = 1;
u = v = s = 1;
int last_ans = 0;
for(reg int i = 2; i <= N; i ++){
int a = read() ^ last_ans;
Add(a, i);
printf("%d
", last_ans = Len + std::max(Dis_2(s)-1, 0));
}
return 0;
}