CF643E. Bear and Destroying Subtrees 期望dp

题目链接

CF643E. Bear and Destroying Subtrees

题解

dp[i][j]表示以i为根的子树中,树高小于等于j的概率
转移就是dp[i][j] = 0.5 + 0.5 (dp[i][j-1]) 首先是边不连的概率,其次是<=dp[son][j -1]的
然后我zz了
对于新增一个点,对于父亲的深度影响只有该节点的深度+1,除掉旧的乘上新的就OK,我全更新了一遍...,写出了奇怪的bug...
对于新点,只需要向上更新60次就好了,因为\(\frac{1}{2^60}\)已经足够小了

代码

#include<cstdio>
#include<algorithm>
#include<vector>
//#define int long long 
using namespace std;
const int maxn = 5 * 1e5 + 10, h = 60;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    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 T, Q, fa[maxn], node; 
double f[maxn][61]; 
main() {
    Q = read(); node = 1;
    for(int i = 0;i < h;++ i) f[node][i] = 1.0; 
    while(Q--) {
        int opt = read(), x = read();
        if(opt == 1) { 
            fa[++ node] = x;  
            for(int i = 0; i < h; i++) f[node][i] = 1; 
            double pre = f[x][0], now; 
            f[x][0] *= 0.5; 
            for(int i = 1; i < h && x; i++, x = fa[x]) { 
                now = f[fa[x]][i]; 
                f[fa[x]][i] /= 0.5 + 0.5 * pre; 
                f[fa[x]][i] *= 0.5 + 0.5 * f[x][i - 1]; 
                pre = now; 
            } 
        } else if(opt == 2) { 
            double ans = 0; 
            for(int i = 0; i < h; i++) ans += i * (f[x][i] - f[x][i - 1]); 
            printf("%.10lf\n", ans); 
        } 
    } 
    return 0; 
}  

猜你喜欢

转载自www.cnblogs.com/sssy/p/9691331.html