题解:
注意到,如果第j位有贡献,那么从i往上跳2^j,然后不能再跳超过2^j。
因此可以考虑倍增。
代码:
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=100233,M=N<<1; struct zs{int too,pre;}e[N<<1]; int tot,last[N],fa[N][18],fae[N][18],num[N],pos[N],TIM,sz[N]; ll sum[N],sume[maxn<<1],ans; int k,n,m,ra,fh; char rx; inline int read() { rx=getchar(),ra=0,fh=1; while((rx<'0'||rx>'9')&&rx!='-')rx=getchar(); if(rx=='-')fh=-1,rx=getchar(); while(rx>='0'&&rx<='9') ra=ra*10+rx-48,rx=getchar();return ra*fh; } void dfs(int x) { int to; pos[++TIM]=x;sz[x]=num[x]=1; for(int i=1;i<18;i++) fa[x][i]=fa[fa[x][i-1]][i-1], fae[x][i]=fae[fa[x][i-1]][i-1]; for(int i=last[x];i;i=e[i].pre) if((to=e[i].too)!=fa[x][0]) fa[to][0]=x,fae[to][0]=i,dfs(to),sz[x]+=sz[to]; } inline void DFS(int x) { register int i,to; for(i=last[x];i;i=e[i].pre)if((to=e[i].too)!=fa[x][0]) ans+=1ll*sume[i]*(sz[x]-sz[to]),DFS(to); } void insert(int a,int b) { e[++tot].too=b,e[tot].pre=last[a],last[a]=tot, e[++tot].too=a,e[tot].pre=last[b],last[b]=tot; } int main() { n=read(); for(int i=1;i<n;i++)insert(read(),read()); dfs(1); int f; for(int j=0;j<18;j++) for(int i=1;i<=n;i++) if((f=fa[k=pos[i]][j])) num[f]+=num[k],sum[f]+=num[k]+sum[k], sume[fae[k][j]]+=num[k]+sum[k]; DFS(1),printf("%lld ",ans); }