[51nod1709]复杂度分析

  给出一棵n个点的树(以1号点为根),定义dep[i]为点i到根路径上点的个数。众所周知,树上最近公共祖先问题可以用倍增算法解决。现在我们需要算出这个算法精确的复杂度。我们定义计算点i和点j最近公共组先的精确复杂度为bit[dep[i]-dep[lca(i,j)]]+bit[dep[j]-dep[lca(i,j)]](bit[i]表示i在二进制表示下有多少个1,lca(i,j)表示点i和点j的最近公共祖先)。为了计算平均所需的复杂度为多少,请你帮忙计算任意两点计算最近公共组先所需复杂度的总和。
即计算 sum{ bit[dep[i]-dep[lca(i,j)]]+bit[dep[j]-dep[lca(i,j)]] } ,1<=i<n,i+1<=j<=n;
 Input
  第一行一个数n表示点数(1<=n<=100,000)
  接下来n-1行每行两个数x,y表示一条边(1<=x,y<=n)
 Output
  一个数表示答案

 

  抱sxt大腿系列。。大概思路就是统计每个点往上跳每一步对答案的贡献。。先倍增预处理出每个点的那些父亲还有到父亲的那条边。

  大概就是统计一下能从子树里跳到当前点的节点数,那些点就能当前父亲其他儿子里能跳到父亲的节点一起贡献。。。

  当然不能每次直接跑。。就把查询都存到到父亲的边里面,最后再dfs一遍统计。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<cmath>
 7 #include<cstdlib>
 8 #include<bitset>
 9 //#include<ctime>
10 #define ll long long
11 #define ull unsigned long long
12 #define ui unsigned int
13 #define d double
14 //#define ld long double
15 using namespace std;
16 const int maxn=100233,mxnode=maxn<<1;
17 struct zs{int too,pre;}e[maxn<<1];int tot,last[maxn];
18 int fa[maxn][18],fae[maxn][18],num[maxn],pos[maxn],TIM,sz[maxn];
19 ll sum[maxn],sume[maxn<<1];
20 int i,j,k,n,m;
21 ll ans;
22 
23 int ra,fh;char rx;
24 inline int read(){
25     rx=getchar(),ra=0,fh=1;
26     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
27     if(rx=='-')fh=-1,rx=getchar();
28     while(rx>='0'&&rx<='9')ra=ra*10+rx-48,rx=getchar();return ra*fh;
29 }
30 
31 inline void dfs(int x){
32     register int i,to;pos[++TIM]=x,sz[x]=num[x]=1;
33     for(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];
34     for(i=last[x];i;i=e[i].pre)if((to=e[i].too)!=fa[x][0])
35         fa[to][0]=x,fae[to][0]=i,dfs(to),sz[x]+=sz[to];
36 }
37 inline void DFS(int x){
38     register int i,to;
39     for(i=last[x];i;i=e[i].pre)if((to=e[i].too)!=fa[x][0])
40         ans+=1ll*sume[i]*(sz[x]-sz[to]),DFS(to);
41 }
42 inline void insert(int a,int b){
43     e[++tot].too=b,e[tot].pre=last[a],last[a]=tot,
44     e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
45 }
46 int main(){
47     n=read();register int i,j;
48     for(i=1;i<n;i++)insert(read(),read());
49     dfs(1);
50     int f;
51     for(j=0;j<18;j++)for(i=1;i<=n;i++)if((f=fa[k=pos[i]][j]))
52         num[f]+=num[k],sum[f]+=num[k]+sum[k],sume[fae[k][j]]+=num[k]+sum[k];
53     DFS(1),printf("%lld\n",ans);
54 }
View Code

 

posted @ 2016-10-13 22:08  czllgzmzl  阅读(448)  评论(0编辑  收藏  举报