CF643E Bear and Destroying Subtrees

题解

我们可以先写出(dp)式来。

(dp[u][i])表示以(u)为根的子树深度不超过(i-1)的概率

(dp[u][i]=prod (dp[v][i-1]+1)*frac{1}{2})

然后因为这道题精度要求比较低,所以我们对于每个(u),保留第二维60个就行了。

所以每次加入一个节点的时候,我们只需要更新父链上60个(dp)值就好了,复杂度(O(n*60))

代码

#include<bits/stdc++.h>
#define N 500002
using namespace std;
typedef long long ll;
const int maxd=60;
int q,n,fa[N];
double dp[N][61];
inline ll rd(){
	ll x=0;char c=getchar();bool f=0;
	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f?-x:x;
}
int main(){
	q=rd();
	int type,x;
	n=1;
	for(int i=0;i<=maxd;++i)dp[1][i]=1;
	while(q--){
		type=rd();x=rd();
		if(type==1){
			++n;
			for(int i=0;i<=maxd;++i)dp[n][i]=1;
			fa[n]=x;
			double pre=1;int s=n;
			for(int dep=0,now=x;now&&dep<=60;dep++,now=fa[now]){
				double nw=dp[now][dep];
				dp[now][dep]/=0.5*(1+pre);
				if(dep)dp[now][dep]*=0.5*(1+dp[s][dep-1]);
				else dp[now][dep]*=0.5;
				s=now;pre=nw;
			}
		}
		else{
			double ans=0;
			for(int i=1;i<=60;++i)ans+=(dp[x][i]-dp[x][i-1])*i;
			printf("%.10lf
",ans);
		}
	}
	return 0;
}
原文地址:https://www.cnblogs.com/ZH-comld/p/11099484.html