.......
考虑树的直径有两个点,,,,,不用每次都O(n)的去遍历.....
直接求出当前加入的点与直径两点的距离,然后判断一下就好了
....不知道这个小技巧的话,还挺难想的
#include<bits/stdc++.h> #define MAXN 1000005 using namespace std; int q,tot,p=0; int h[MAXN],z[MAXN],f[30][MAXN],dep[MAXN],jl[MAXN],lx=2,mx=4,maxl=2; struct node{ int from,to,next; }e[MAXN<<1]; void init(){ memset(h,-1,sizeof(h)); memset(f,0,sizeof(f)); tot=0; p=4; } void add(int x,int y){ tot++; e[tot].from=x; e[tot].to=y; e[tot].next=h[x]; h[x]=tot; } int dfs(int now,int fa){ dep[now]=dep[fa]+1; for(int i=h[now];i!=(-1);i=e[i].next){ if(e[i].to!=fa){ f[0][e[i].to]=now; dfs(e[i].to,now); } } } int lca(int x,int y){ if(dep[x]<dep[y])swap(x,y); int dx=dep[x]-dep[y]; for(int i=0;i<=22;i++){ if((1<<i)&dx){ x=f[i][x]; } } if(x==y)return x; for(int i=22;i>=0;i--){ if(f[i][x]!=f[i][y]){ x=f[i][x]; y=f[i][y]; } } return f[0][x]; } int dis(int x,int y){ return dep[x]+dep[y]-2*dep[lca(x,y)]; } int main(){ cin>>q;init(); add(1,2),add(2,1); add(1,3),add(3,1); add(1,4),add(4,1); for(int i=1;i<=q;i++){ //cin>>jl[i]; scanf("%d",&jl[i]); z[jl[i]]=p; add(jl[i],p+1),add(p+1,jl[i]); add(jl[i],p+2),add(p+2,jl[i]); p+=2; } dfs(1,1); for(int i=1;i<=22;i++){ for(int j=1;j<=p;j++){ f[i][j]=f[i-1][f[i-1][j]]; } } for(int i=1;i<=q;i++){ int px=z[jl[i]]+1; int x=dis(px,lx),y=dis(px,mx); if(x>y){ if(x>maxl){ mx=px; maxl=x; } } else{ if(y>maxl){ lx=px; maxl=y; } } cout<<maxl<<endl; } }