长链剖分模板题
只能按深度统计,同时比DSU on tree难理解一些,但是复杂度少个log
对每个点抓出向下延伸最长的儿子叫做长儿子。在合并时用指针继承信息,对于长儿子O(1)继承,其他儿子暴力
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=1000005; 6 int len[N],imp[N],ans[N]; 7 int p[N],noww[2*N],goal[2*N]; 8 int mem[N],*pts[N],*fpt=mem+1; 9 int n,t1,t2,cnt; 10 void Link(int f,int t) 11 { 12 noww[++cnt]=p[f]; 13 goal[cnt]=t,p[f]=cnt; 14 } 15 void DFS(int nde,int fth,int dth) 16 { 17 for(int i=p[nde];i;i=noww[i]) 18 if(goal[i]!=fth) 19 { 20 DFS(goal[i],nde,dth+1); 21 if(len[goal[i]]>len[imp[nde]]) 22 imp[nde]=goal[i]; 23 } 24 len[nde]=len[imp[nde]]+1; 25 } 26 void Getans(int nde,int fth) 27 { 28 pts[nde][0]=1; 29 if(imp[nde]) 30 { 31 pts[imp[nde]]=pts[nde]+1; 32 Getans(imp[nde],nde),ans[nde]=ans[imp[nde]]+1; 33 } 34 for(int i=p[nde];i;i=noww[i]) 35 if(goal[i]!=fth&&goal[i]!=imp[nde]) 36 { 37 pts[goal[i]]=fpt,fpt+=len[goal[i]],Getans(goal[i],nde); 38 for(int j=1;j<=len[goal[i]];j++) 39 { 40 pts[nde][j]+=pts[goal[i]][j-1]; 41 int b1=(j<=ans[nde]&&pts[nde][j]>=pts[nde][ans[nde]]); 42 int b2=(j>ans[nde]&&pts[nde][j]>pts[nde][ans[nde]]); 43 if(b1||b2) ans[nde]=j; 44 } 45 } 46 if(pts[nde][ans[nde]]==1) ans[nde]=0; 47 } 48 int main() 49 { 50 scanf("%d",&n); 51 for(int i=1;i<n;i++) 52 { 53 scanf("%d%d",&t1,&t2); 54 Link(t1,t2),Link(t2,t1); 55 } 56 DFS(1,0,0),pts[1]=fpt,fpt+=len[1]; 57 Getans(1,0); 58 for(int i=1;i<=n;i++) 59 printf("%d ",ans[i]); 60 return 0; 61 }