[CF643E]Bear and Destroying Subtrees(期望,忽略误差)

Posted cnyali-tea

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF643E]Bear and Destroying Subtrees(期望,忽略误差)相关的知识,希望对你有一定的参考价值。

Description:

? 给你一棵初始只有根为1的树

? 两种操作

? 1 x 表示加入一个新点以 x为父亲

? 2 x 表示以 x 为根的子树期望最深深度

? 每条边都有 \(\frac12\) 的概率断裂。

Solution:

\[ E(\max\A\) \not=\max\E(A)\ \]

? 所以一般会从定义出发,设 \(dp[x][i]\) 表示以 \(x\) 为根,深度为 \(i\) 的概率。

? 然后不好确定这个深度是在哪取到,所以可以设 \(dp[x][i]\) 为深度 \(\le i\) 的概率,不难发现这样每个子树就是独立的了。
\[ dp[x][i] = \prod_v\in son(x)\fracdp[x][i - 1] + 12 \]
? 加1是因为 \((x, v)\) 这条边可能会断,那么如果断了,那么 \(dep\le i - 1\) 的概率一定是1。

? 深度较大时期望值很小(它的缩减率是指数级的), 因为允许精度误差所以可以忽略. 加入每个点时把上面 50 个祖先的 \(dp\) 值更新一下即可。

Summary:

? 在难以刻画细小的状态时可以将状态设广范些,但要保证前后可以互相转换。

Code:

#include <vector>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>

typedef long long LL;
typedef unsigned long long uLL;

#define fir first
#define sec second
#define SZ(x) ((int)x.size())
#define ALL(x) (x).begin(), (x).end()
#define MP(x, y) std::make_pair(x, y)
#define PB(x) push_back(x)
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO cerr << "GO" << endl;
#define DE(x) cerr << x << endl;
#define rep(i, a, b) for (register int i = (a), i##_end_ = (b); (i) <= i##_end_; ++ (i))
#define drep(i, a, b) for (register int i = (a), i##_end_ = (b); (i) >= i##_end_; -- (i))
#define REP(i, a, b) for (register int i = (a), i##_end_ = (b); (i) < i##_end_; ++ (i))

inline int read() 
    register int x = 0; register int f = 1; register char c;
    while (!isdigit(c = getchar())) if (c == '-') f = -1;
    while (x = (x << 1) + (x << 3) + (c xor 48), isdigit(c = getchar()));
    return x * f;


template<class T> inline void write(T x) 
    static char stk[30]; static int top = 0;
    if (x < 0)  x = -x, putchar('-'); 
    while (stk[++top] = x % 10 xor 48, x /= 10, x);
    while (putchar(stk[top--]), top);


template<typename T> inline bool chkmin(T &a, T b)  return a > b ? a = b, 1 : 0; 
template<typename T> inline bool chkmax(T &a, T b)  return a < b ? a = b, 1 : 0; 

using namespace std;

const int maxN = 5e5 + 1;
const int D = 50;

int Q, fa[maxN], ncnt;
double dp[maxN][D];

void clear(int x, int son, int cnt)

    if (!x || cnt >= D) return;
    clear(fa[x], x, cnt + 1);
    for (int i = 1; i < D; ++i)
        dp[x][i] /= 0.5 * (dp[son][i - 1] + 1);


void update(int x, int son, int cnt)

    if (!x || cnt >= D) return;
    for (int i = 1; i < D; ++i)
        dp[x][i] *= 0.5 * (dp[son][i - 1] + 1);
    update(fa[x], x, cnt + 1);


double ask(int x)

    double ans(0);
    for (int i = 1; i < D; ++i)
        ans += (double) i * (dp[x][i] - dp[x][i - 1]);
    return ans;


int main() 

#ifndef ONLINE_JUDGE
    freopen("xhc.in", "r", stdin);
    freopen("xhc.out", "w", stdout);
#endif
    Q = read();
    ncnt = 1;
    fa[1] = 0;
    fill(dp[1], dp[1] + D, 1);
    while (Q--)
    
        int op = read(), x = read();
        if (op == 1)
        
            fa[++ncnt] = x;
            clear(fa[x], x, 1);
            fill(dp[ncnt], dp[ncnt] + D, 1);
            dp[x][0] *= 0.5;
            update(x, ncnt, 0);
         else 
        
            printf("%.7lf\n", ask(x));
        
    
    return 0;

以上是关于[CF643E]Bear and Destroying Subtrees(期望,忽略误差)的主要内容,如果未能解决你的问题,请参考以下文章

cf B. Bear and Compressing

CF771C Bear and Tree Jumps 题解

CF573E Bear and Bowling

CF 643 E. Bear and Destroying Subtrees

CF679C(Bear and Square Grid) 经典好题

cf643E. Bear and Destroying Subtrees(期望dp)