给出一棵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 }
时间: 2024-10-06 21:48:56