51nod1709复杂度分析

题解:

注意到,如果第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);
}
原文地址:https://www.cnblogs.com/xuanyiming/p/7506684.html