CF643E Bear and Destroying Subtrees (期望DP)

洛谷:题目链接
首先要确认这是一个期望DP.
线性性质就不必说了.
设f[x][i]表示以x为根,\(dep[x_{son}] <= h\)的概率
那么答案就是.\(\sum_{h = 1}^{MAX\_H}h * (f[x][h] - f[x][h - 1])\)
考虑如何更新.
显然,可以通过\(x_{son}\)转移,那么子节点\(v = son_x\)有两种情况,一个是存在边,对\(f[x][h]\)贡献\(1/2 * f[v][h - 1]\)的概率,二十不存在该边,概率那么就是\(1/2\)
然后就成了\(f[x][h] = \prod_{v = son_x}(1/2 + 1/2 * f[v][h - 1])\)
更新的时候暴力更新即可,一直往上直到根节点.除掉以前的项,乘上新的项即可.
但是如果深度特别大怎么办,注意题目中的有精度误差,那么到了很大的数就会比\(1e-6\)小,这个时候精度达到了,不用继续.这里选择取\(Max\_H = 60\).
CODE

#include <iostream>
#include <cstdio>
const int maxN = 5e5 + 7;
const int maxH = 60;

int n,fa[maxN];
double f[maxN][maxH];

inline int read() {
	int x = 0,f = 1;char c = getchar();
	while(c < '0' || c > '9' ) {if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
	return x * f;
}

int main() {
	int n = 1,T = read(),opt,x;
	for(int i = 0;i < maxH;++ i) f[1][i] = 1;
	while(T --) {
		opt = read();x = read();
		if(opt == 1) {
			fa[++ n] = x;
			for(int i = 0;i < maxH;++ i) 
				f[n][i] = 1;
			double tmp1 = f[x][0],tmp2;
			f[x][0] *= 0.5;
			for(int Fa = fa[x],i = 1; Fa && i < maxH; Fa = fa[x = Fa],++ i)
            {
                tmp2 = f[Fa][i];
                f[Fa][i] /= 0.5 + 0.5 * tmp1;
                f[Fa][i] *= 0.5 + 0.5 * f[x][i-1];
                tmp1 = tmp2;
        	}
		}
		else {
			double ans = 0;
			for(int i = 1;i < maxH;++ i) 
			ans += (f[x][i] - f[x][i - 1]) * i;
			printf("%.10lf\n",ans);
		}
	}
	return 0;
}
posted @ 2018-09-22 21:48  Rlif  阅读(207)  评论(0编辑  收藏  举报