星球大战

星球大战
有一棵树。每次可以攻击树上的某棵子树,然后这棵子树上的每条边有(frac{1}{2})的概率消失。定义 若攻击以x为根的子树,深度ht(x)为x子树剩余点(与x连通)的最大深度。共q次操作,两种: 1 x.新建一个节点,其父节点为x。2 x.询问若攻击以x为根的子树,x子树的期望深度。 (qleq 5 imes10^5)

设dp[i][j]为以i为根的子树,深度<=j的概率.

(ans=sum_{dep=1}^{max_h}dep imes(dp[x][dep]-dp[x][dep-1]))

转移方程:(dp[x][dep]=Pi_{yin son(x)}(frac{1}{2}+frac{1}{2}dp[y][dep-1]))

其中第一个(frac{1}{2})是x->y的边断掉的概率

(frac{1}{2}dp[y][dep-1])是x->y没有断掉的概率乘以y节点深度<=dep-1的概率.

对于每次加点,先除以修改前的(frac{1}{2}+frac{1}{2}dp[y][dep-1]),再乘以修改后的(frac{1}{2}+frac{1}{2}dp[y][dep-1])

for(int dep=0;dep<65;++dep)p[id][dep]=1;
while(q--){
    read(op,x);
    if(op==1){
        fa[++id]=x;
        for(int dep=0;dep<65;++dep)p[id][dep]=1;
        double pre=p[x][0];
        p[x][0]*=0.5;
        double now=p[x][0];
        for(int dep=1;(x=fa[x])>0&&dep<65;++dep){
            double tmp=p[x][dep];
            p[x][dep]/=1+pre;//x子儿子y修改前的值
            p[x][dep]*=1+now;//x子儿子y修改后的值
            pre=tmp,now=p[x][dep];
        }
    }else{
        double ans=0;
        for(int dep=1;dep<65;++dep)
            ans+=(double)dep*(p[x][dep]-p[x][dep-1]);
        printf("%.10f
",ans);
    }
}
原文地址:https://www.cnblogs.com/foursmonth/p/14161926.html