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\n",ans);
		}
	}
	return 0;
}
posted @ 2019-06-27 20:34  comld  阅读(222)  评论(0编辑  收藏  举报