Problem:
J: X-percent Blooming
Spring is coming. Cherry blossom forecast is one of the things we feel spring is just around the corner. International Cherry-blossom
Prediction Committee (ICPC) is an organization that announces the state of cherry blossoms every spring. Your task as a staff of the
organization is to observe a specific cherry tree and evaluate the level of the blossom of the cherry tree.
The tree that you observe can be considered as a graph tree. There is a root node with no parent node, and the other nodes have only one
parent node. Let $d(v)$ be the minimum distance from node $v$ to the leaf nodes of the subtree of $v$. Here, a leaf node is a node that has no
child nodes. Then a node $v$ blooms if $d(v) \leq O$ at the time you observe. On the other hand, at full blossom, a node $v$ blooms if $d(v) \leq F$.
The level of cherry blossom is evaluated as the ratio of the numbers of blooming nodes at the time you observe and full blossom. More
formally, let $b(x)$ be the number of nodes $v$ satisfying $d(v) \leq x$. The level of cherry blossom is defined as $b(O) / b(F)$.
Note that the tree is also growing. When the tree grows, a new node is added to a node as a child node. So the number of nodes might be
increased between your observations.
Initially, the tree had only one node, which is the root node. You recorded the growth and observation time but forgot to record the level
of cherry blossom on each observation. Now, your new task is to restore the data of the levels of cherry blossom from the given records.
For Sample 1, the tree at the first observation looks like the figure below, where green border means a node is a leaf and pink circle
means a node that blooms. The left tree represents a tree without blossom. The center tree represents blossom at the time you observe and
the right tree represents full blossom.
Figure J-1. First observation of Sample 1
Similarly, the following figure illustrates the second observation of Sample 1.
Figure J-2. Second observation of Sample 1
Input
The input consists of a single test case in the format below.
$Q$ $O$ $F$
$query_1$
:
$query_Q$
The first line contains three integers $Q$ ($1 \leq Q \leq 10^5$), $O$ ($0 \leq O \leq 10^5$), $F$ ($O \leq F \leq 10^5$). $Q$ is the number of records you stored. $O$ is the threshold of distances to determine blooming nodes at the time you observe. $F$ is the threshold of distances to determine blooming
nodes at full blossom. The $i$-th of the following $Q$ lines represents the $i$-th recorded event. An event is either of two types of events:
Growth event: a new node is added as a child node of the $k_i$-th added node, where the root node is the $0$-th added node. For this
type of event, $query_i$ is '$1$ $k_i$'.
Observation event: evaluate the level of cherry blossom on the state of the tree at that time. For this type of event, $query_i$ is '$2$'.
  Note that whether each node bloomed in the past does not matter to the current observation. The node $v$ does not b
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i, n) for(ll i =0; i < ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B>
bool chmax(A &a, B b) { return a<b && (a=b, true); }
template <class A, class B>
bool chmin(A &a, B b) { return b<a && (a=b, true); }

struct HLD {
  int N;
  int g;
  V<V<int>> t;
  V<int> par, dep, sz, pp, stov, vtos, px, index;
  HLD(int N, V<V<int>> graph, int root)
      : N(N), g(0), t(move(graph)), par(N, -1),
      dep(N), sz(N, 1), pp(N), stov(N), vtos(N),
      px(N), index(N) {
    dfs1(root);
    dfs2(root);
  }
  void dfs1(int v) {
    for (auto& w : t[v]){
      t[w].erase(find(t[w].begin(), t[w].end(), v));
      par[w] = v;
      dep[w] = dep[v] + 1;
      dfs1(w);
      sz[v] += sz[w];
      if(sz[t[v][0]] < sz[w]) swap(t[v][0], w);
    }
  }
  void dfs2(int v) {
    vtos[v] = g;
    stov[g++] = v;
    for (auto w : t[v]){
      int f = w == t[v][0];
      pp[w] = f ? pp[v] : w;
      px[w] = px[v] + 1 - f;
      dfs2(w);
    }
  }
  int lca(int a, int b) {
    if (px[pp[a]] > px[pp[b]]) swap(a, b);
    while (px[pp[a]] < px[pp[b]]) b = par[pp[b]];
    while (pp[a] != pp[b]) {
      a = par[pp[a]];
      b = par[pp[b]];
    }
    return dep[a] < dep[b] ? a : b;
  }
  auto query_half(int r, int a, bool edge = false) {
    vector<pair<int,int>> res(px[a] - px[r] + 1);
    while (px[a] > px[r]) {
      res[px[a] - px[r]] = { vtos[pp[a]], vtos[a] + 1 };
      a = par[pp[a]];
    }
    res[0] = { vtos[r] + edge, vtos[a] + 1 };
    return res;
  }
  // return vector<pair<int,int>>
  // a -> b
  // l<rなら[l:r)、l>rなら[r:l)の逆順
  // edge=trueの場合はlcaを含まない区間を返す
  auto query(int a, int b, bool edge = false) {
    int g = lca(a, b);
    auto l = query_half(g, b, edge);
    auto r = query_half(g, a, 1);
    for(auto& q : r) swap(q.first, q.second);
    l.insert(l.begin(), r.rbegin(), r.rend());
    return l;
  }
  // 返り値は縮約後の縮約後の頂点集合 vector<int> と
  // 木の辺の集合 vector<pair<int,int>> !! もとの頂点番号 !!
  // もし reindex したいなら index[v] を見ればいい
  pair<V<int>, V<pair<int, int>>> ComputeTree(V<int> vs) {
    auto comp = [&](int x, int y) { return vtos[x] < vtos[y]; };
    sort(vs.begin(), vs.end(), comp);
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    int K = vs.size();
    REP(i, K - 1) vs.push_back(lca(vs[i], vs[i + 1]));
    sort(vs.begin(), vs.end(), comp);
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    K = vs.size();
    REP(i, K) index[vs[i]] = i;
    V<pair<int, int>> es;
    REP(i, K - 1) {
      int p = lca(vs[i], vs[i + 1]);
      es.push_back({ vs[i + 1], p });
    }
    return {vs, es};
  }
};

template <class S, class F, S op(S, S),
          F composition(F, F), S mapping(F, S)>
struct LazySegtree {
  int n, s, log;
  S e;
  F id;
  V<S> d;
  V<F> lz;

  void update(int k) {
    d[k] = op(d[2 * k], d[2 * k + 1]);
  }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < s) lz[k] = composition(f, lz[k]);
    // if(d[k].fail) push(k), update(k);
  }
  void push(int k) {
    all_apply(2 * k, lz[k]);
    all_apply(2 * k + 1, lz[k]);
    lz[k] = id;
  }
  void pushx(int p){
    for (int i = log; i >= 1; i--) push(p >> i);
  }
  void updx(int p){
    for (int i = 1; i <= log; i++) update(p >> i);
  }
  
  LazySegtree() = default;
  LazySegtree(unsigned n, S e, F id)
      : n(n), s(bit_ceil(n)), e(e), id(id) {
    log = countr_zero((unsigned)s);
    d.assign(2 * s, e), lz.assign(s, id);
  }
  LazySegtree(const vector<S>& v, S e, F id)
      : LazySegtree(v.size(), e, id) {
    ranges::copy(v, d.begin() + s);
    for (int i = s - 1; i >= 1; i--) update(i);
  }
  void set(int p, S x) {
    pushx(p += s);
    d[p] = x;
    updx(p);
  }
  S get(int p) {
    pushx(p += s);
    return d[p];
  }
  S prod(int l, int r) {
    if (l == r) return e;
    pushx(l += s), pushx((r += s) - 1);
    S sml = e, smr = e;
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1, r >>= 1;
    }
    return op(sml, smr);
  }
  void apply(int l, int r, F f) {
    if (l == r) return;
    if((l += s) > s) pushx(l - 1);
    if((r += s) < s * 2) pushx(r);
    int l2 = l, r2 = r;
    while (l < r) {
      if (l & 1) all_apply(l++, f);
      if (r & 1) all_apply(--r, f);
      l >>= 1, r >>= 1;
    }
    if(l2 > s) updx(l2 - 1);
    if(r2 < s * 2) updx(r2);
  }
  template <class G>
  int max_right(int l, G f) {
    if (l == n) return n;
    pushx(l += s);
    S sm = e;
    while (1) {
      while (l % 2 == 0) l >>= 1;
      S t = op(sm, d[l]);
      if (!f(t)) break;
      sm = t;
      if (l++, (l & -l) == l) return n;
    }
    while (l < s) {
      push(l);
      l = 2 * l;
      if (S t = op(sm, d[l]); f(t)) sm = t, l++;
    }
    return l - s;
  }
  template <class G>
  int min_left(int r, G f) {
    if (r == 0) return 0;
    pushx((r += s) - 1);
    S sm = e;
    while (1) {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      S t = op(d[r], sm);
      if (!f(t)) break;
      sm = t;
      if ((r & -r) == r) return 0;
    }
    while (r < s) {
      push(r);
      r = 2 * r + 1;
      if (S t = op(d[r], sm); f(t)) sm = t, r--;
    }
    return r + 1 - s;
  }
};

struct S {
    int val, num;
};
S op(S l, S r) {
    if(l.val > r.val) return r;
    if(l.val < r.val) return l;
    return S(l.val, l.num+r.num);
}
int composition(int a, int b) { return a+b; }
S mapping(int f, S x) {
    return S(x.val+f, x.num);
};

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int q, o, f; cin >> q >> o >> f;
    V<int> par = {-1};
    V<pair<string, int>> queries;
    for(int i = 1; i <= q; i++) {
        int op; cin >> op;
        if(op == 1) {
            queries.emplace_back("add", ssize(par));
            int p; cin >> p;
            par.push_back(p);
        } else {
            queries.emplace_back("calc", ssize(par));
        }
    }
    int n = ssize(par);
    V<V<int>> g(n);
    for(int i = 1; i < n; i++) {
        g[i].push_back(par[i]);
        g[par[i]].push_back(i);
    }
    V<V<int>> dpar(20, V<int>(n, -1));
    dpar[0] = par;
    REP(i, 19) REP(j, n) {
        if(dpar[i][j] == -1) continue;
        dpar[i+1][j] = dpar[i][dpar[i][j]];
    }
    auto climb = [&](int u, int k) {
        for(int b = 19; b >= 0; b--) {
            if(k>>b&1) {
                if(u != -1) u = dpar[b][u];
            }
        }
        return u;
    };
    auto hld = HLD(n, g, 0);
    auto sumi = [](int a, int b) { return a+b; };
    LazySegtree<S, int, op, composition, mapping> sego(n, S(1<<29, 0), 0);
    LazySegtree<S, int, op, composition, mapping> segf(n, S(1<<29, 0), 0);
    sego.set(hld.vtos[0], S(1, 1));
    segf.set(hld.vtos[0], S(1, 1));
    auto add_on_path = [&](auto& seg, int u, int v, int x) {
        for(auto [l, r] : hld.query(u, v)) {
            if(l > r) swap(l, r);
            seg.apply(l, r, x);
        }
    };
    cout << fixed << setprecision(10);
    V<int> is_leaf(n, 1);
    for(auto [op, u] : queries) {
        if(op == "add") {
            sego.set(hld.vtos[u], S(0, 1));
            segf.set(hld.vtos[u], S(0, 1));
            int p = par[u];
            int vo = climb(u, o); if(vo == -1) vo = 0;
            int vf = climb(u, f); if(vf == -1) vf = 0;

            add_on_path(sego, u, vo, 1);
            add_on_path(segf, u, vf, 1);

            if(is_leaf[p]) {
                is_leaf[p] = 0;
                int vop = par[vo]; if(vop == -1) vop = 0;
                add_on_path(sego, p, vop, -1);
                int vfp = par[vf]; if(vfp == -1) vfp = 0;
                add_on_path(segf, p, vfp, -1);
            }
        } else {
            S pro = sego.prod(0, n);
            double osum = pro.val == 0 ? u-pro.num : u;
            S prf = segf.prod(0, n);
            double fsum = prf.val == 0 ? u-prf.num : u;
            cout << osum / fsum << '\n';
        }
    }
}
accuracy: 1
time_ms: 200
memory_kb: 28720
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i, n) for(ll i =0; i < ll(n); i++)
template <class T> using V = vector<T>;
template <class A, class B>
bool chmax(A &a, B b) { return a<b && (a=b, true); }
template <class A, class B>
bool chmin(A &a, B b) { return b<a && (a=b, true); }

struct HLD {
  int N;
  int g;
  V<V<int>> t;
  V<int> par, dep, sz, pp, stov, vtos, px, index;
  HLD(int N, V<V<int>> graph, int root)
      : N(N), g(0), t(move(graph)), par(N, -1),
      dep(N), sz(N, 1), pp(N), stov(N), vtos(N),
      px(N), index(N) {
    dfs1(root);
    dfs2(root);
  }
  void dfs1(int v) {
    for (auto& w : t[v]){
      t[w].erase(find(t[w].begin(), t[w].end(), v));
      par[w] = v;
      dep[w] = dep[v] + 1;
      dfs1(w);
      sz[v] += sz[w];
      if(sz[t[v][0]] < sz[w]) swap(t[v][0], w);
    }
  }
  void dfs2(int v) {
    vtos[v] = g;
    stov[g++] = v;
    for (auto w : t[v]){
      int f = w == t[v][0];
      pp[w] = f ? pp[v] : w;
      px[w] = px[v] + 1 - f;
      dfs2(w);
    }
  }
  int lca(int a, int b) {
    if (px[pp[a]] > px[pp[b]]) swap(a, b);
    while (px[pp[a]] < px[pp[b]]) b = par[pp[b]];
    while (pp[a] != pp[b]) {
      a = par[pp[a]];
      b = par[pp[b]];
    }
    return dep[a] < dep[b] ? a : b;
  }
  auto query_half(int r, int a, bool edge = false) {
    vector<pair<int,int>> res(px[a] - px[r] + 1);
    while (px[a] > px[r]) {
      res[px[a] - px[r]] = { vtos[pp[a]], vtos[a] + 1 };
      a = par[pp[a]];
    }
    res[0] = { vtos[r] + edge, vtos[a] + 1 };
    return res;
  }
  // return vector<pair<int,int>>
  // a -> b
  // l<rなら[l:r)、l>rなら[r:l)の逆順
  // edge=trueの場合はlcaを含まない区間を返す
  auto query(int a, int b, bool edge = false) {
    int g = lca(a, b);
    auto l = query_half(g, b, edge);
    auto r = query_half(g, a, 1);
    for(auto& q : r) swap(q.first, q.second);
    l.insert(l.begin(), r.rbegin(), r.rend());
    return l;
  }
  // 返り値は縮約後の縮約後の頂点集合 vector<int> と
  // 木の辺の集合 vector<pair<int,int>> !! もとの頂点番号 !!
  // もし reindex したいなら index[v] を見ればいい
  pair<V<int>, V<pair<int, int>>> ComputeTree(V<int> vs) {
    auto comp = [&](int x, int y) { return vtos[x] < vtos[y]; };
    sort(vs.begin(), vs.end(), comp);
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    int K = vs.size();
    REP(i, K - 1) vs.push_back(lca(vs[i], vs[i + 1]));
    sort(vs.begin(), vs.end(), comp);
    vs.erase(unique(vs.begin(), vs.end()), vs.end());
    K = vs.size();
    REP(i, K) index[vs[i]] = i;
    V<pair<int, int>> es;
    REP(i, K - 1) {
      int p = lca(vs[i], vs[i + 1]);
      es.push_back({ vs[i + 1], p });
    }
    return {vs, es};
  }
};

template <class S, class F, S op(S, S),
          F composition(F, F), S mapping(F, S)>
struct LazySegtree {
  int n, s, log;
  S e;
  F id;
  V<S> d;
  V<F> lz;

  void update(int k) {
    d[k] = op(d[2 * k], d[2 * k + 1]);
  }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < s) lz[k] = composition(f, lz[k]);
    // if(d[k].fail) push(k), update(k);
  }
  void push(int k) {
    all_apply(2 * k, lz[k]);
    all_apply(2 * k + 1, lz[k]);
    lz[k] = id;
  }
  void pushx(int p){
    for (int i = log; i >= 1; i--) push(p >> i);
  }
  void updx(int p){
    for (int i = 1; i <= log; i++) update(p >> i);
  }
  
  LazySegtree() = default;
  LazySegtree(unsigned n, S e, F id)
      : n(n), s(bit_ceil(n)), e(e), id(id) {
    log = countr_zero((unsigned)s);
    d.assign(2 * s, e), lz.assign(s, id);
  }
  LazySegtree(const vector<S>& v, S e, F id)
      : LazySegtree(v.size(), e, id) {
    ranges::copy(v, d.begin() + s);
    for (int i = s - 1; i >= 1; i--) update(i);
  }
  void set(int p, S x) {
    pushx(p += s);
    d[p] = x;
    updx(p);
  }
  S get(int p) {
    pushx(p += s);
    return d[p];
  }
  S prod(int l, int r) {
    if (l == r) return e;
    pushx(l += s), pushx((r += s) - 1);
    S sml = e, smr = e;
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1, r >>= 1;
    }
    return op(sml, smr);
  }
  void apply(int l, int r, F f) {
    if (l == r) return;
    if((l += s) > s) pushx(l - 1);
    if((r += s) < s * 2) pushx(r);
    int l2 = l, r2 = r;
    while (l < r) {
      if (l & 1) all_apply(l++, f);
      if (r & 1) all_apply(--r, f);
      l >>= 1, r >>= 1;
    }
    if(l2 > s) updx(l2 - 1);
    if(r2 < s * 2) updx(r2);
  }
  template <class G>
  int max_right(int l, G f) {
    if (l == n) return n;
    pushx(l += s);
    S sm = e;
    while (1) {
      while (l % 2 == 0) l >>= 1;
      S t = op(sm, d[l]);
      if (!f(t)) break;
      sm = t;
      if (l++, (l & -l) == l) return n;
    }
    while (l < s) {
      push(l);
      l = 2 * l;
      if (S t = op(sm, d[l]); f(t)) sm = t, l++;
    }
    return l - s;
  }
  template <class G>
  int min_left(int r, G f) {
    if (r == 0) return 0;
    pushx((r += s) - 1);
    S sm = e;
    while (1) {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      S t = op(d[r], sm);
      if (!f(t)) break;
      sm = t;
      if ((r & -r) == r) return 0;
    }
    while (r < s) {
      push(r);
      r = 2 * r + 1;
      if (S t = op(d[r], sm); f(t)) sm = t, r--;
    }
    return r + 1 - s;
  }
};


int sumi(int a, int b) { return a+b; };

int main() {
    cin.tie(0)->sync_with_stdio(0);
    int q, o, f; cin >> q >> o >> f;
    V<int> par = {-1};
    V<pair<string, int>> queries;
    for(int i = 1; i <= q; i++) {
        int op; cin >> op;
        if(op == 1) {
            queries.emplace_back("add", ssize(par));
            int p; cin >> p;
            par.push_back(p);
        } else {
            queries.emplace_back("calc", -1);
        }
    }
    int n = ssize(par);
    V<V<int>> g(n);
    for(int i = 1; i < n; i++) {
        g[i].push_back(par[i]);
        g[par[i]].push_back(i);
    }
    V<V<int>> dpar(20, V<int>(n, -1));
    dpar[0] = par;
    REP(i, 19) REP(j, n) {
        if(dpar[i][j] == -1) continue;
        dpar[i+1][j] = dpar[i][dpar[i][j]];
    }
    auto climb = [&](int u, int k) {
        for(int b = 19; b >= 0; b--) {
            if(k>>b&1) {
                if(u != -1) u = dpar[b][u];
            }
        }
        return u;
    };
    auto hld = HLD(n, g, 0);
    LazySegtree<int, int, sumi, sumi, sumi> sego(n, 0, 0);
    LazySegtree<int, int, sumi, sumi, sumi> segf(n, 0, 0);
    sego.set(hld.vtos[0], 1);
    segf.set(hld.vtos[0], 1);
    int osum = 1, fsum = 1;
    auto add_on_path = [&](auto& seg, int u, int v, int x) {
        for(auto [l, r] : hld.query(u, v)) {
            if(l > r) swap(l, r);
            seg.apply(l, r, x);
        }
    };
    cout << fixed << setprecision(10);
    V<int> is_leaf(n, 1);
    for(auto [op, u] : queries) {
        if(op == "add") {
            int p = par[u];
            int vo = climb(u, o); if(vo == -1) vo = 0;
            int vf = climb(u, f); if(vf == -1) vf = 0;

            add_on_path(sego, u, vo, 1);
            {
                int tmp = u;
                while(sego.get(hld.vtos[tmp]) == 1) {
                    osum++;
                    if(tmp == vo) break;
                    tmp = par[tmp];
                }
            }

            add_on_path(segf, u, vf, 1);
            {
                int tmp = u;
                while(segf.get(hld.vtos[tmp]) == 1) {
                    fsum++;
                    if(tmp == vf) break;
                    tmp = par[tmp];
                }
            }

            if(is_leaf[p]) {
                is_leaf[p] = 0;
                int vop = par[vo]; if(vop == -1) vop = 0;
                add_on_path(sego, p, vop, -1);
                if(sego.get(hld.vtos[vop]) == 0) osum--;

                int vfp = par[vf]; if(vfp == -1) vfp = 0;
                add_on_path(segf, p, vfp, -1);
                if(segf.get(hld.vtos[vfp]) == 0) fsum--;
            }
        } else {
            cout << (double)osum / fsum << '\n';
        }
    }
}
accuracy: 0.4444444444444444
time_ms: 130
memory_kb: 23728
final_rank: 8

code_snippet: #include <bits/stdc++.h>
using namespace std;

// =============================================================================================================
// === Segtree Library
// =============================================================================================================
class RangeAddMin {
    public:
    int size_ = 1;
    vector<pair<int, int>> dat;
    vector<int> laz;
    
    void init(int sz) {
        while (size_ <= sz) size_ *= 2;
        dat.resize(size_ * 2, make_pair(0, 0));
        laz.resize(size_ * 2, 0);
        for (int i = 0; i < size_; i++) {
            int cx = size_ + i;
            dat[cx].second = 1;
            while (cx >= 2) {
                cx >>= 1; dat[cx].second += 1;
            }
        }
    }

    pair<int, int> merged(pair<int, int> v1, pair<int, int> v2) {
        if (v1.first < v2.first) return v1;
        if (v1.first > v2.first) return v2;
        return make_pair(v1.first, v1.second + v2.second);
    }

    void refresh(int pos) {
        if (pos < size_) {
            laz[pos * 2 + 0] += laz[pos];
            laz[pos * 2 + 1] += laz[pos];
            laz[pos] = 0;
            pair<int, int> v1 = dat[pos * 2 + 0]; v1.first += laz[pos * 2 + 0];
            pair<int, int> v2 = dat[pos * 2 + 1]; v2.first += laz[pos * 2 + 1];
            dat[pos] = merged(v1, v2);
        }
        else {
            dat[pos].first += laz[pos];
            laz[pos] = 0;
        }
    }

    void add_(int l, int r, int x, int a, int b, int u) {
        if (l <= a && b <= r) { laz[u] += x; return; }
        if (r <= a || b <= l) return;
        refresh(u);
        add_(l, r, x, a, (a + b) / 2, u * 2 + 0);
        add_(l, r, x, (a + b) / 2, b, u * 2 + 1);
        refresh(u);
    }

    void add(int l, int r, int x) {
        return add_(l, r, x, 0, size_, 1);
    }

    pair<int, int> query_(int l, int r, int a, int b, int u) {
        if (l <= a && b <= r) { refresh(u); return dat[u]; }
        if (r <= a || b <= l) return make_pair((1 << 30), 0);
        refresh(u);
        pair<int, int> v1 = query_(l, r, a, (a + b) / 2, u * 2 + 0);
        pair<int, int> v2 = query_(l, r, (a + b) / 2, b, u * 2 + 1);
        return merged(v1, v2);
    }

    pair<int, int> query(int l, int r) {
        return query_(l, r, 0, size_, 1);
    }
};


// =============================================================================================================
// === Functions
// =============================================================================================================
void dfs1(int pos, vector<int> &dp, vector<vector<int>> &G) {
    dp[pos] = 1;
    for (int to : G[pos]) {
        dfs1(to, dp, G);
        dp[pos] += dp[to];
    }
}

void dfs2(int pos, int cur, vector<int> &ord, vector<int> &num_normal, vector<int> &root, vector<int> &dp, vector<vector<int>> &G) {
    ord.push_back(pos);
    num_normal[pos] = cur;
    pair<int, int> max_dp = make_pair(-1, -1);
    for (int to : G[pos]) max_dp = max(max_dp, make_pair(dp[to], to));

    // Recursion
    if (G[pos].size() >= 1) {
        root[max_dp.second] = root[pos];
        dfs2(max_dp.second, cur + 1, ord, num_normal, root, dp, G);
        for (int to : G[pos]) {
            if (to == max_dp.second) continue;
            root[to] = pos;
            dfs2(to, 0, ord, num_normal, root, dp, G);
        }
    }
}

void add_len(int pos, int x, int lens, vector<int> &ord, vector<int> &num_normal, vector<int> &root, RangeAddMin &Z) {
    // cerr << "Add " << pos << " " << x << " " << lens << endl;
    int cx = pos;
    while (lens > 0 && cx != -1) {
        int addi = min(lens, num_normal[cx] + 1);
        // cerr << "added " << ord[cx] - addi + 1 << " " << ord[cx] + 1 << " " << x << endl;
        Z.add(ord[cx] - addi + 1, ord[cx] + 1, x);
        cx = root[cx];
        lens -= addi;
    }
}

// =============================================================================================================
// === Main Part
// =============================================================================================================
int main() {
    // Step 1. Input
    int Q, O, F; scanf("%d%d%d", &Q, &O, &F);
    vector<tuple<int, int, int>> Query(Q);
    int N = 1;
    for (int i = 0; i < Q; i++) {
        scanf("%d", &get<0>(Query[i]));
        if (get<0>(Query[i]) == 1) {
            scanf("%d", &get<1>(Query[i]));
            get<2>(Query[i]) = N;
            N += 1;
        }
    }

    // Step 2. HLD
    vector<vector<int>> G(N, vector<int>(0, 0));
    vector<int> dp(N, 0);
    vector<int> orders;
    vector<int> ord(N, 0);
    vector<int> root(N, -1);
    vector<int> num_normal(N, 0);
    for (int i = 0; i < Q; i++) {
        if (get<0>(Query[i]) == 2) continue;
        G[get<1>(Query[i])].push_back(get<2>(Query[i]));
    }

    // Step 3. DFS
    dfs1(0, dp, G);
    dfs2(0, 0, orders, num_normal, root, dp, G);
    for (int i = 0; i < orders.size(); i++) ord[orders[i]] = i;

    // Step 4. Process Query: Init
    RangeAddMin Z1; Z1.init(N + 2);
    RangeAddMin Z2; Z2.init(N + 2);
    vector<bool> is_leaf(N, false);
    is_leaf[0] = true;
    add_len(0, +1, O + 1, ord, num_normal, root, Z1);
    add_len(0, +1, F + 1, ord, num_normal, root, Z2);
    int verts = 1;

    // Step 5. Process Query: Main
    for (int i = 0; i < Q; i++) {
        if (get<0>(Query[i]) == 1) {
            int idx = get<2>(Query[i]);
            int par = get<1>(Query[i]);
            if (is_leaf[par] == true) {
                is_leaf[par] = false;
                add_len(par, -1, O + 1, ord, num_normal, root, Z1);
                add_len(par, -1, F + 1, ord, num_normal, root, Z2);
            }
            is_leaf[idx] = true;
            add_len(idx, +1, O + 1, ord, num_normal, root, Z1);
            add_len(idx, +1, F + 1, ord, num_normal, root, Z2);
            verts += 1;
        }
        else {
            pair<int, int> s1 = Z1.query(0, N);
            pair<int, int> s2 = Z2.query(0, N);
            int num_bloom1 = (N - s1.second); if (s1.first != 0) num_bloom1 = verts;
            int num_bloom2 = (N - s2.second); if (s2.first != 0) num_bloom2 = verts;
            /*cerr << "! " << s1.first << " " << s1.second << endl;
            cerr << "! " << s2.first << " " << s2.second << endl;
            cerr << verts << " " << num_bloom1 << " " << num_bloom2 << endl;*/
            printf("%.12lf\n", 1.0 * num_bloom1 / num_bloom2);
        }
    }
    return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 18708
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

template <typename M, typename N, M (*f)(M, M), M (*g)(M, N), N (*h)(N, N),
          M (*m1)(), N (*n1)()>
class LazySegmentTree {
    int n, sz, height;
    vector<M> data;
    vector<N> lazy;
    void update(int k) {
        data[k] = f(data[k * 2], data[k * 2 + 1]);
    }
    void apply(int k, N x) {
        data[k] = g(data[k], x);
        if (k < sz)
            lazy[k] = h(lazy[k], x);
    }
    void down(int k) {
        apply(k * 2, lazy[k]);
        apply(k * 2 + 1, lazy[k]);
        lazy[k] = n1();
    }

  public:
    LazySegmentTree(int n = 0) : LazySegmentTree(vector<M>(n, m1())) {}
    LazySegmentTree(const vector<M> &a) : n(SZ(a)) {
        sz = 1, height = 0;
        while (sz < (int)a.size())
            sz <<= 1, height++;
        data.assign(2 * sz, m1());
        lazy.assign(sz, n1());
        rep(i, 0, a.size()) data[sz + i] = a[i];
        for (int i = sz - 1; i; i--)
            update(i);
    }
    M operator[](int k) const {
        k += sz;
        rrep(i, 1, height + 1) down(k >> i);
        return data[k];
    }
    vector<M> get() {
        rep(k, 1, sz) down(k);
        return {data.begin() + sz, data.begin() + sz + n};
    }
    void set(int k, M x) {
        k += sz;
        for (int i = height; i; i--)
            down(k >> i);
        data[k] = x;
        for (int i = 1; i <= height; i++)
            update(k >> i);
    }
    void update(int L, int R, N x) {
        if (L >= R)
            return;
        L += sz, R += sz;
        for (int i = height; i; i--) {
            if (((L >> i) << i) != L)
                down(L >> i);
            if (((R >> i) << i) != R)
                down((R - 1) >> i);
        }
        int lb = L, rb = R;
        while (L < R) {
            if (L & 1)
                apply(L++, x);
            if (R & 1)
                apply(--R, x);
            L >>= 1;
            R >>= 1;
        }
        L = lb, R = rb;
        for (int i = 1; i <= height; i++) {
            if (((L >> i) << i) != L)
                update(L >> i);
            if (((R >> i) << i) != R)
                update((R - 1) >> i);
        }
    }
    M query(int L, int R) {
        if (L >= R)
            return m1();
        L += sz, R += sz;
        for (int i = height; i; i--) {
            if (((L >> i) << i) != L)
                down(L >> i);
            if (((R >> i) << i) != R)
                down((R - 1) >> i);
        }
        M lb = m1(), rb = m1();
        while (L < R) {
            if (L & 1)
                lb = f(lb, data[L++]);
            if (R & 1)
                rb = f(data[--R], rb);
            L >>= 1;
            R >>= 1;
        }
        return f(lb, rb);
    }
    template <class F> int max_right(int L, F ch) {
        if (L == n)
            return n;
        L += sz;
        rrep(i, 1, height + 1) down(L >> i);
        M sum = m1();
        do {
            while (L % 2 == 0)
                L >>= 1;
            if (!ch(f(sum, data[L]))) {
                while (L < sz) {
                    down(L);
                    L <<= 1;
                    if (ch(f(sum, data[L])))
                        sum = f(sum, data[L++]);
                }
                return L - sz;
            }
            sum = f(sum, data[L++]);
        } while ((L & -L) != L);
        return n;
    }
    template <class F> int min_left(int R, F ch) {
        if (R == 0)
            return 0;
        R += sz;
        rrep(i, 1, height + 1) down((R - 1) >> i);
        M sum = m1();
        do {
            R--;
            while (R > 1 and (R & 1))
                R >>= 1;
            if (!ch(f(data[R], sum))) {
                while (R < sz) {
                    down(R);
                    R = (R * 2 + 1);
                    if (ch(f(data[R], sum))) {
                        sum = f(data[R--], sum);
                    }
                }
                return R + 1 - sz;
            }
            sum = f(data[R], sum);
        } while ((R & -R) != R);
        return 0;
    }
};

/**
 * @brief Lazy Segment Tree
 */

struct HLD{
    using P=pair<int,int>;
    vector<vector<int>> g; vector<int> sz,in,out,rev,hs,par,dist;
    void dfs(int v,int p){
        par[v]=p; sz[v]=1;
        if(p!=-1)dist[v]=dist[p]+1;
        if(!g[v].empty() and g[v][0]==p)swap(g[v][0],g[v].back());
        for(auto& to:g[v])if(to!=p){
           dfs(to,v); sz[v]+=sz[to];
           if(sz[g[v][0]]<sz[to])swap(g[v][0],to);
        }
    }
    void dfs2(int v,int p,int& k){
        in[v]=k++; rev[in[v]]=v;
        for(auto& to:g[v])if(to!=p){
            hs[to]=(g[v][0]==to?hs[v]:to);
            dfs2(to,v,k);
        }
        out[v]=k;
    }
    HLD(int _n):g(_n),sz(_n),in(_n),out(_n),rev(_n),hs(_n),par(_n),dist(_n){}
    void add_edge(int u,int v){
        g[u].emplace_back(v); g[v].emplace_back(u);
    }
    void run(int rt=0){dfs(rt,-1); hs[rt]=rt; int k=0; dfs2(rt,-1,k);}
    int lca(int u,int v){
        for(;;v=par[hs[v]]){
            if(in[u]>in[v])swap(u,v);
            if(hs[u]==hs[v])return u;
        }
    }
    vector<P> get(int u,int p,bool es=0){
        assert(in[p]<=in[u] and out[u]<=out[p]);
        vector<P> res;
        while(hs[u]!=hs[p]){
            res.push_back({in[hs[u]],in[u]+1});
            u=par[hs[u]];
        }
        res.push_back({in[p]+es,in[u]+1});
        return res;
    }
    int jump(int u,int v,int k){
        if(k<0)return -1;
        int g=lca(u,v);
        int d0=dist[u]+dist[v]-dist[g]*2;
        if(d0<k)return -1;
        int st=u;
        if(dist[u]-dist[g]<k)st=v,k=d0-k;
        for(;;){
            int to=hs[st];
            if(in[st]-k>=in[to])return rev[in[st]-k];
            k-=in[st]-in[to]+1; st=par[to];
        }
    }
};

/**
 * @brief Heavy Light Decomposition
 */

pair<int,int> f(pair<int,int> A, pair<int,int> B) {
    if (A.first < B.first) return A;
    if (A.first > B.first) return B;
    return {A.first, A.second + B.second};
}

pair<int,int> g(pair<int,int> A, int B) {
    return {A.first + B, A.second};
}

int h(int A, int B) {return A+B;}

pair<int,int> e1() {return {inf, 0};}

int e2() {return 0;}

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int Q, X, Y;
    cin >> Q >> X >> Y;
    vector<int> A(Q), ID(Q);
    int Cur = 1;
    rep(i,0,Q) {
        int t;
        cin >> t;
        if (t == 1) {
            cin >> A[i], ID[i] = Cur, Cur++;
        }
        else A[i] = ID[i] = -1;
    }
    int N = Cur;
    HLD G(N);
    rep(i,0,Q) {
        if (A[i] >= 0) G.add_edge(A[i], ID[i]);
    }
    G.run();
    LazySegmentTree<pair<int,int>,int,f,g,h,e1,e2> SegX(vector<pair<int,int>>(N,{0,1})), SegY(vector<pair<int,int>>(N,{0,1}));
    SegX.update(G.in[0], G.in[0]+1, 1), SegY.update(G.in[0], G.in[0]+1, 1);
    vector<bool> B(N, false);
    B[0] = true;
    rep(i,0,Q) {
        if (A[i] >= 0) {
            int Par = A[i], Now = ID[i];
            if (B[Par]) {
                B[Par] = false;
                int AX = G.jump(Par, 0, min(X, G.dist[Par]));
                auto p = G.get(Par, AX);
                for(auto [a,b] : p) SegX.update(a, b, -1);
                int AY = G.jump(Par, 0, min(Y, G.dist[Par]));
                p = G.get(Par, AY);
                for(auto [a,b] : p) SegY.update(a, b, -1);
            }
            {
                B[Now] = true;
                int AX = G.jump(Now, 0, min(X, G.dist[Now]));
                auto p = G.get(Now, AX);
                for(auto [a,b] : p) SegX.update(a, b, 1);
                int AY = G.jump(Now, 0, min(Y, G.dist[Now]));
                p = G.get(Now, AY);
                for(auto [a,b] : p) SegY.update(a, b, 1);
            }
        }
        else {
            auto ansx = SegX.query(0,N);
            auto ansy = SegY.query(0,N);
            int ANSX = (ansx.first == 0 ? ansx.second : 0);
            int ANSY = (ansy.first == 0 ? ansy.second : 0);
            printf("%.12f\n", (double)(N-ANSX) / (double)(N-ANSY));
        }
    }
}
accuracy: 1
time_ms: 160
memory_kb: 15976
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

struct S{
    ll m,num;
};
S e() { return {ll(1e9),0ll}; };
S op(S a, S b) {
    S res;
    if(a.m==b.m){
        res.m=a.m;
        res.num=a.num+b.num;
    }
    else res=(a.m<b.m?a:b);
    return res;
}

struct lazy_segtree {
    
    int _n, size, log;
    vector<S> d;
    vector<ll> lz;

    lazy_segtree() : lazy_segtree(0) {}
    lazy_segtree(int n) : lazy_segtree(vector<S>(n, e())) {}
    lazy_segtree(const vector<S>& v) : _n(int(v.size())) {
        log = ceil_pow2(_n);
        size = 1 << log;
        d = vector<S>(2 * size, e());
        lz = vector<ll>(size, 0);
        for (int i = 0; i < _n; i++) d[size + i] = v[i];
        for (int i = size - 1; i >= 1; i--) {
            update(i);
        }
    }
    int ceil_pow2(int n) {
        int x = 0;
        while ((1U << x) < (unsigned int)(n)) x++;
        return x;
    }

    S get(int p) {
        p += size;
        for (int i = log; i >= 1; i--) push(p >> i);
        return d[p];
    }

    S all_prod() { return d[1]; }

    void apply(int l, int r, ll f) {
        if (l == r) return;

        l += size;
        r += size;

        for (int i = log; i >= 1; i--) {
            if (((l >> i) << i) != l) push(l >> i);
            if (((r >> i) << i) != r) push((r - 1) >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1;
                r >>= 1;
            }
            l = l2;
            r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if (((l >> i) << i) != l) update(l >> i);
            if (((r >> i) << i) != r) update((r - 1) >> i);
        }
    }

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
    void all_apply(int k, ll f) {
        d[k].m+=f;
        if (k < size) lz[k]+=f;
    }
    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = 0;
    }
};



struct HLD {
    using T = ll;

    vector<vector<int>> G;
    vector<int> siz, depth, par, in, out, head, heavy, ch;
    bool edge = 0;
    int cur_pos = 0;
    
    lazy_segtree seg;

    HLD() = default;
    HLD(const vector<vector<int>>& G) :G(G), siz(G.size()), depth(G.size()), par(G.size(), -1), in(G.size()), out(G.size()), head(G.size()), heavy(G.size(), -1), ch(G.size(), 0) {
        dfs(0);
        decompose(0, 0);
        vector<S> V(G.size(),S({ll(1e9),1}));
        seg = lazy_segtree(V);
    };

    void update(int u, int v,ll x) {
        while (head[u] != head[v]) {
            if (in[head[u]] > in[head[v]])swap(u, v);
            seg.apply(in[head[v]], in[v] + 1,x);
            v = par[head[v]];
        }
        if (in[u] > in[v])swap(u, v);
        seg.apply(in[u], in[v] + 1,x);
    }

    ll get(){
        S res=seg.all_prod();
        if(res.m!=0)return 0;
        else return res.num;
    }

    void dfs(int v) {
        siz[v] = 1;
        int max_siz = 0;
        for (int c : G[v]) {
            if (c == par[v])continue;
            par[c] = v;
            depth[c] = depth[v] + 1;
            dfs(c);
            siz[v] += siz[c];
            if (siz[c] > max_siz) {
                max_siz = siz[c];
                heavy[v] = c;
            }
        }
    }
    void decompose(int v, int h) {
        head[v] = h;
        in[v] = cur_pos++;
        if (heavy[v] != -1)decompose(heavy[v], h);
        for (int c : G[v]) {
            if (c != par[v] && c != heavy[v])decompose(c, c);
        }
        out[v] = cur_pos;
    }
};

vector<vector<ll>> D(1,vector<ll>(20,-1));
ll k_th_anc(ll x,ll k){
    for(int i=0;i<20;i++){
        if(k&(1<<i))x=D[x][i];
        if(x<0)return 0;
    }
    return x;
}

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    int Q,O,F;
    cin >> Q>>O>>F;

    vector<vector<int>> G(1);
    vector<pair<int,int>> query(Q);
    
    for(int i=0;i<Q;i++){
        cin>>query[i].first;
        if(query[i].first==1){
            cin>>query[i].second;
            int v=G.size();
            G.push_back({});
            G[query[i].second].push_back(v);
            G[v].push_back(query[i].second);
            D.push_back(vector<ll>(20,-1));
            D.back()[0]=query[i].second;
        }
    }
    int N=G.size();
    for(int i=1;i<20;i++){
        for(int j=0;j<N;j++){
            if(D[j][i-1]<0)continue;
            D[j][i]=D[D[j][i-1]][i-1];
        }
    }

    HLD HO(G),HF(G);
    HO.update(0,0,ll(-1e9)+1);
    HF.update(0,0,ll(-1e9)+1);
    ll n=1;
    cout<<fixed<<setprecision(15);
    vector<bool> leef(N,0);
    leef[0]=1;
    for(int q=0;q<Q;q++){
        if(query[q].first==1){
            int v=n,p=query[q].second,rF,rO;;
            n++;
            HO.update(v,v,ll(-1e9));
            HF.update(v,v,ll(-1e9));
            if(leef[p]){
                leef[p]=0;
                HF.update(k_th_anc(p,F),p,-1);
                HO.update(k_th_anc(p,O),p,-1);
            }
            leef[v]=1;
            HF.update(k_th_anc(v,F),v,1);
            HO.update(k_th_anc(v,O),v,1);
        }
        if(query[q].first==2){
            cout<<double(n-HO.get())/double(n-HF.get())<<endl;
        }
    }
}
accuracy: 1
time_ms: 280
memory_kb: 44404
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define ll long long
#define elif else if
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, l, r) for (int i = l; i < (r); i++)

/*
LazySegmentTree(n, f, g, h, M1, OM0) : サイズ n の初期化。
  - f : 要素をマージする二項演算
  - g : 要素に作用させる二項演算
  - h : 作用素同士をマージする二項演算
  - M1 : モノイドの単位元
  - OM0 : 作用素の単位元
build() : segtree の構築
update(a, b, x) : 区間 [a, b) に作用素 x を適用する。
*/
template <typename Mo, typename Op = Mo>
struct LazySegmentTree
{
  using F = function<Mo(Mo, Mo)>;
  using G = function<Mo(Mo, Op)>;
  using H = function<Op(Op, Op)>;

  int sz, height;
  vector<Mo> data;
  vector<Op> lazy;
  const F f;
  const G g;
  const H h;
  const Mo M1;
  const Op OM0;

  LazySegmentTree(
      int n, const F f, const G g, const H h, const Mo &M1, const Op OM0)
      : f(f), g(g), h(h), M1(M1), OM0(OM0)
  {
    sz = 1;
    height = 0;
    while (sz < n)
      sz <<= 1, height++;
    data.assign(2 * sz, M1);
    lazy.assign(2 * sz, OM0);
  }

  void set(int k, const Mo &x) { data[k + sz] = x; }

  void build()
  {
    for (int k = sz - 1; k > 0; k--)
    {
      data[k] = f(data[2 * k + 0], data[2 * k + 1]);
    }
  }

  inline void propagate(int k)
  {
    if (lazy[k] != OM0)
    {
      lazy[2 * k + 0] = h(lazy[2 * k + 0], lazy[k]);
      lazy[2 * k + 1] = h(lazy[2 * k + 1], lazy[k]);
      data[k] = reflect(k);
      lazy[k] = OM0;
    }
  }

  inline Mo reflect(int k)
  {
    return lazy[k] == OM0 ? data[k] : g(data[k], lazy[k]);
  }

  inline void recalc(int k)
  {
    while (k >>= 1)
      data[k] = f(reflect(2 * k + 0), reflect(2 * k + 1));
  }

  inline void thrust(int k)
  {
    for (int i = height; i > 0; i--)
      propagate(k >> i);
  }

  void update(int a, int b, const Op &x)
  {
    thrust(a += sz);
    thrust(b += sz - 1);
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1)
    {
      if (l & 1)
        lazy[l] = h(lazy[l], x), ++l;
      if (r & 1)
        --r, lazy[r] = h(lazy[r], x);
    }
    recalc(a);
    recalc(b);
  }

  Mo query(int a, int b)
  {
    thrust(a += sz);
    thrust(b += sz - 1);
    Mo L = M1, R = M1;
    for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1)
    {
      if (l & 1)
        L = f(L, reflect(l++));
      if (r & 1)
        R = f(reflect(--r), R);
    }
    return f(L, R);
  }

  Mo operator[](const int &k) { return query(k, k + 1); }
};

class HLD
{
private:
  void dfs_sz(int v)
  {
    auto &es = G[v];
    if (~par[v])
      es.erase(find(es.begin(), es.end(), par[v]));

    for (int &u : es)
    {
      par[u] = v;
      dfs_sz(u);
      sub[v] += sub[u];
      if (sub[u] > sub[es[0]])
        swap(u, es[0]);
    }
  }

  void dfs_hld(int v, int &pos)
  {
    vid[v] = pos++;
    inv[vid[v]] = v;
    for (int u : G[v])
    {
      if (u == par[v])
        continue;
      nxt[u] = (u == G[v][0] ? nxt[v] : u);
      dfs_hld(u, pos);
    }
  }

public:
  vector<vector<int>> G;
  // vid: vertex -> idx
  // inv: idx -> vertex
  vector<int> vid, nxt, sub, par, inv;

  HLD(int n) : G(n), vid(n, -1), nxt(n), sub(n, 1), par(n, -1), inv(n) {}

  void add_edge(int u, int v)
  {
    G[u].emplace_back(v);
    G[v].emplace_back(u);
  }

  void build(int r = 0)
  {
    int pos = 0;
    dfs_sz(r);
    nxt[r] = r;
    dfs_hld(r, pos);
  }

  int lca(int u, int v)
  {
    while (1)
    {
      if (vid[u] > vid[v])
        swap(u, v);
      if (nxt[u] == nxt[v])
        return u;
      v = par[nxt[v]];
    }
  }

  vector<pair<int, int>> for_each_vertex(int u, int v)
  {
    /*
    seg[HLD.vid[v]]=w
    */
    vector<pair<int, int>> paths;
    while (1)
    {
      if (vid[u] > vid[v])
        swap(u, v);
      if (nxt[u] != nxt[v])
      {
        paths.push_back({vid[nxt[v]], vid[v] + 1});
        v = par[nxt[v]];
      }
      else
      {
        paths.push_back({vid[u], vid[v] + 1});
        return paths;
      }
    }
  }
};

using S = pair<int, int>;
using F = int;
S op(S a, S b)
{
  if (a.first < b.first)
    return a;
  if (a.first > b.first)
    return b;
  return {a.first, a.second + b.second};
}
S e = {1 << 30, 0};
S mapping(S x, F f)
{
  return {x.first + f, x.second};
}
F composition(F f, F g) { return f + g; }
F ID = 0;

int main()
{
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout << fixed << setprecision(10);

  int Q, C0, C1;
  cin >> Q >> C0 >> C1;
  vector<pair<int, int>> query, edges;
  vi par(Q + 1, -1);
  int idx1 = 1;
  rep(i, Q)
  {
    int t;
    cin >> t;
    if (t == 1)
    {
      int p;
      cin >> p;
      edges.push_back({p, idx1});
      query.push_back({p, idx1});
      par[idx1] = p;
      idx1++;
    }
    else
    {
      query.push_back({-1, i});
    }
  }

  int N = idx1;
  par.resize(N);
  vvi table;
  table.push_back(par);
  int LOG = 17;
  rep2(i, 1, LOG)
  {
    vi table_i(N, -1);
    rep(j, N)
    {
      if (table[i - 1][j] != -1)
        table_i[j] = table[i - 1][table[i - 1][j]];
    }
    table.push_back(table_i);
  }

  auto up = [&](int v, int k) -> int
  {
    int now = v;
    for (int i = LOG - 1; i >= 0; i--)
    {
      if ((k >> i) & 1)
      {
        now = table[i][now];
        if (now == -1)
          return 0;
      }
    }
    return now;
  };

  HLD hld(N);
  for (auto [u, v] : edges)
  {
    hld.add_edge(u, v);
  }
  hld.build();
  vector<vector<int>> cnt(2, vi(Q, -1));
  rep(t, 2)
  {
    LazySegmentTree<S, F> seg(N, op, mapping, composition, e, ID);
    seg.set(hld.vid[0], {1, 1});
    int C;
    if (t == 0)
      C = C0;
    else
      C = C1;
    int sz = 1;
    vi leaf(N, 0);
    leaf[0] = 1;
    rep(i, Q)
    {
      auto [x, y] = query[i];
      if (x != -1)
      {
        if (leaf[x])
        {
          int px = up(x, C);
          for (auto [l, r] : hld.for_each_vertex(x, px))
          {
            seg.update(l, r, -1);
          }
        }
        leaf[x] = 0;
        leaf[y] = 1;
        seg.set(hld.vid[y], {0, 1});
        int py = up(y, C);
        for (auto [l, r] : hld.for_each_vertex(y, py))
        {
          seg.update(l, r, 1);
        }
        sz++;
      }
      else
      {
        S val = seg.query(0, N);
        int zero = 0;
        if (val.first == 0)
          zero = val.second;
        cnt[t][i] = sz - zero;
      }
    }
  }
  rep(i, Q)
  {
    if (cnt[0][i] != -1)
    {
      double ans = 1.0 * cnt[0][i] / cnt[1][i];
      cout << ans << "\n";
    }
  }
}
accuracy: 1
time_ms: 280
memory_kb: 18932
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, l, r) for (int i = (l); i < r; ++i)
#define rrep(i, l, r) for (int i = (r - 1); i >= l; --i)
#define all(c) begin(c), end(c)

#ifdef LOCAL
#define debug(...) debug_impl(#__VA_ARGS__, __VA_ARGS__)
template <class H, class... Ts> void debug_impl(string s, H&& h, Ts &&... ts) {
  cerr << '(' << s << "): (" << forward<H>(h);
  ((cerr << ", " << forward<Ts>(ts)), ..., (cerr << ")\n"));
}
#else
#define debug(...) void(0)
#endif

template <class T> bool chmax(T& a, const T& b) {
  return b > a ? (a = b, true) : false;
}
template <class T> bool chmin(T& a, const T& b) {
  return b < a ? (a = b, true) : false;
}

template <class T> istream& operator>>(istream& in, vector<T>& v) {
  for (auto& e : v) in >> e;
  return in;
}
template <class ... Args> void read(Args &... args) {
  (cin >> ... >> args);
}
template <class T> ostream& operator<<(ostream& out, const vector<T>& v) {
  int n = v.size();
  rep(i, 0, n) {
    out << v[i];
    if (i + 1 != n) out << ' ';
  }
  return out;
}
template <class H, class ... Ts> void print(H&& h, Ts &&...ts) {
  cout << h, ((cout << " " << forward<Ts>(ts)), ..., (cout << "\n"));
}

struct io_setup_ {
  io_setup_() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} io_setup{};

int ceil_log2(int n) {
  int l = 0;
  while (1 << l < n) ++l;
  return l;
}


template <class S,
  S(*op)(S, S),
  S(*e)(),
  class F,
  S(*mapping)(F, S),
  F(*composition)(F, F),
  F(*id)()>
struct lazy_segtree {
public:
  lazy_segtree(): lazy_segtree(0) {}
  explicit lazy_segtree(int n): lazy_segtree(std::vector<S>(n, e())) {}
  explicit lazy_segtree(const std::vector<S>& v): _n(int(v.size())) {
    log = ceil_log2(_n);
    size = 1 << log;
    d = std::vector<S>(2 * size, e());
    lz = std::vector<F>(size, id());
    for (int i = 0; i < _n; i++) d[size + i] = v[i];
    for (int i = size - 1; i >= 1; i--) {
      update(i);
    }
  }

  void set(int p, S x) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = x;
    for (int i = 1; i <= log; i++) update(p >> i);
  }

  S get(int p) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    return d[p];
  }

  S prod(int l, int r) {
    assert(0 <= l && l <= r && r <= _n);
    if (l == r) return e();

    l += size;
    r += size;

    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }

    S sml = e(), smr = e();
    while (l < r) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
      l >>= 1;
      r >>= 1;
    }

    return op(sml, smr);
  }

  S all_prod() { return d[1]; }

  void apply(int p, F f) {
    assert(0 <= p && p < _n);
    p += size;
    for (int i = log; i >= 1; i--) push(p >> i);
    d[p] = mapping(f, d[p]);
    for (int i = 1; i <= log; i++) update(p >> i);
  }
  void apply(int l, int r, F f) {
    assert(0 <= l && l <= r && r <= _n);
    if (l == r) return;

    l += size;
    r += size;

    for (int i = log; i >= 1; i--) {
      if (((l >> i) << i) != l) push(l >> i);
      if (((r >> i) << i) != r) push((r - 1) >> i);
    }

    {
      int l2 = l, r2 = r;
      while (l < r) {
        if (l & 1) all_apply(l++, f);
        if (r & 1) all_apply(--r, f);
        l >>= 1;
        r >>= 1;
      }
      l = l2;
      r = r2;
    }

    for (int i = 1; i <= log; i++) {
      if (((l >> i) << i) != l) update(l >> i);
      if (((r >> i) << i) != r) update((r - 1) >> i);
    }
  }

  template <bool (*g)(S)> int max_right(int l) {
    return max_right(l, [](S x) { return g(x); });
  }
  template <class G> int max_right(int l, G g) {
    assert(0 <= l && l <= _n);
    assert(g(e()));
    if (l == _n) return _n;
    l += size;
    for (int i = log; i >= 1; i--) push(l >> i);
    S sm = e();
    do {
      while (l % 2 == 0) l >>= 1;
      if (!g(op(sm, d[l]))) {
        while (l < size) {
          push(l);
          l = (2 * l);
          if (g(op(sm, d[l]))) {
            sm = op(sm, d[l]);
            l++;
          }
        }
        return l - size;
      }
      sm = op(sm, d[l]);
      l++;
    } while ((l & -l) != l);
    return _n;
  }

  template <bool (*g)(S)> int min_left(int r) {
    return min_left(r, [](S x) { return g(x); });
  }
  template <class G> int min_left(int r, G g) {
    assert(0 <= r && r <= _n);
    assert(g(e()));
    if (r == 0) return 0;
    r += size;
    for (int i = log; i >= 1; i--) push((r - 1) >> i);
    S sm = e();
    do {
      r--;
      while (r > 1 && (r % 2)) r >>= 1;
      if (!g(op(d[r], sm))) {
        while (r < size) {
          push(r);
          r = (2 * r + 1);
          if (g(op(d[r], sm))) {
            sm = op(d[r], sm);
            r--;
          }
        }
        return r + 1 - size;
      }
      sm = op(d[r], sm);
    } while ((r & -r) != r);
    return 0;
  }

private:
  int _n, size, log;
  std::vector<S> d;
  std::vector<F> lz;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < size) lz[k] = composition(f, lz[k]);
  }
  void push(int k) {
    all_apply(2 * k, lz[k]);
    all_apply(2 * k + 1, lz[k]);
    lz[k] = id();
  }
};

template <
  class T, T(*op)(T, T), T(*e)(),
  class F, T(*mapping)(F, T), F(*composition)(F, F), F(*id)()
>
struct segtree {
  segtree(int n = 0): segtree(vector<T>(n, e())) {}
  segtree(const vector<T>& v): n(v.size()), lg(ceil_log2(n)), siz(1 << lg), d(2 * siz, e()), laz(siz, id()) {
    rep(i, 0, n) d[siz + i] = v[i];
    rrep(i, 1, siz) update(i);
  }

  void set(int p, T x) {
    p += siz;
    down(p);
    d[p] = x;
    up(p);
  }

  T get(int p) {
    p += siz;
    down(p);
    return d[p];
  }
  T prod(int l, int r) {
    if (l == r) return e();
    l += siz, r += siz;
    down(l), down(r, true);
    T sml = e(), smr = e();
    for (; l < r; l >>= 1, r >>= 1) {
      if (l & 1) sml = op(sml, d[l++]);
      if (r & 1) smr = op(d[--r], smr);
    }
    return op(sml, smr);
  }
  T all_prod() {
    return d[1];
  }

  void apply(int l, int r, F f) {
    if (l == r) return;
    l += siz, r += siz;
    down(l), down(r, true);
    for (int l2 = l, r2 = r; l2 < r2; l2 >>= 1, r2 >>= 1) {
      if (l2 & 1) all_apply(l2++, f);
      if (r2 & 1) all_apply(--r2, f);
    }
    up(l), up(r, true);
  }

private:
  int n, lg, siz;
  vector<T> d;
  vector<F> laz;

  void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }
  void all_apply(int k, F f) {
    d[k] = mapping(f, d[k]);
    if (k < siz) laz[k] = composition(f, laz[k]);
  }
  void push(int k) {
    all_apply(2 * k, laz[k]);
    all_apply(2 * k + 1, laz[k]);
    laz[k] = id();
  }
  void down(int p, bool f = false) {
    rrep(i, 1, lg + 1) {
      if (p >> i) push((p - f) >> i);
    }
  }
  void up(int p, bool f = false) {
    rep(i, 1, lg + 1) if (p >> i) update((p - f) >> i);
  }
};

struct HLD {
  int n;
  vector<int> visit, leave, head, ord, siz, par, dep;
private:
  int dfs(vector<vector<int>>& g, int u, int p) {
    par[u] = p;
    int maxsiz = 0;
    for (int& v : g[u]) if (v != p) {
      dep[v] = dep[u] + 1;
      siz[u] += dfs(g, v, u);
      if (chmax(maxsiz, siz[v])) swap(g[u][0], v);
    }
    return siz[u];
  }
  int time = 0;
  void hld(const vector<vector<int>>& g, int u, int p) {
    visit[u] = time, ord[time] = u, ++time;
    head[u] = p >= 0 and g[p][0] == u ? head[p] : u;
    for (int v : g[u]) if (v != p) hld(g, v, u);
    leave[u] = time;
  }
public:
  HLD() = default;
  HLD(vector<vector<int>>& g): n(g.size()), visit(n), leave(n), head(n), ord(n), siz(n, 1), par(n, -1), dep(n) {
    dfs(g, 0, -1);
    hld(g, 0, -1);
  }
  vector<pair<int, int>> get_path(int u, int v) {
    vector<pair<int, int>> res;
    for (;; v = par[head[v]]) {
      if (visit[u] > visit[v]) swap(u, v);
      if (head[u] == head[v]) break;
      res.emplace_back(visit[head[v]], visit[v] + 1);
    }
    res.emplace_back(visit[u], visit[v] + 1);
    return res;
  }
};

pair<int, int> op(pair<int, int> x, pair<int, int> y) {
  if (x.first != y.first) return min(x, y);
  return { x.first, x.second + y.second };
}
pair<int, int> e() {
  return { 100000000, 0 };
}
pair<int, int> mapping(int f, pair<int, int> x) {
  return { x.first + f, x.second };
}
int composition(int f, int g) {
  return f + g;
}
int id() {
  return 0;
}

vector<int> solve(vector<vector<int>> g, int d) {
  const int n = g.size();

  vector<int> par(n, -1);

  vector<int> la(n, -1);

  vector<int> pd(g.size());
  vector<int> stk;
  auto dfs = [&](auto dfs, int u) -> void {
    if (stk.size() >= d) {
      int val = d ? stk.end()[-d] : u;
      la[u] = val;
    }
    stk.push_back(u);
    for (int v : g[u]) {
      par[v] = u;
      dfs(dfs, v);
    }
    stk.pop_back();
  };
  dfs(dfs, 0);

  HLD hld(g);

  lazy_segtree<pair<int, int>, op, e, int, mapping, composition, id> seg(vector<pair<int, int>>(n, { 100000000, 1 }));

  debug(la);

  vector<int> ch_cnt(n);

  int qcnt = 0;

  vector<int> cnt(n);
  rep(i, 0, n) {
    int val = seg.get(hld.visit[i]).first;
    seg.set(hld.visit[i], { 0, 1 });

    int u = max(la[i], 0);

    for (auto [l, r] : hld.get_path(i, u)) {
      ++qcnt;
      seg.apply(l, r, 1);
    }

    int p = par[i];
    if (p >= 0 and ++ch_cnt[p] == 1) {
      u = max(la[p], 0);

      for (auto [l, r] : hld.get_path(p, u)) {
        ++qcnt;
        seg.apply(l, r, -1);
      }
    }

    auto [mv, c] = seg.all_prod();

    debug(mv, c);
    if (mv == 0) {
      cnt[i] = i + 1 - c;
    } else {
      cnt[i] = i + 1;
    }
  }
  return cnt;
}

int main() {
  int q, o, f;
  read(q, o, f);
  vector<vector<int>> g(1);

  vector<int> qs;

  rep(qid, 0, q) {
    int t;
    read(t);
    if (t == 1) {
      int p;
      read(p);
      int v = g.size();
      g[p].push_back(v);
      g.emplace_back();
    } else {
      int siz = g.size();
      qs.push_back(siz - 1);
    }
  }

  vector<int> dO = solve(g, o);
  vector<int> dF = solve(g, f);

  debug(dO);
  debug(dF);

  for (int x : qs) {
    print((double) dO[x] / dF[x]);
  }
}
accuracy: 1
time_ms: 210
memory_kb: 19524
final_rank: 4

code_snippet: #include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cassert>
using namespace std;

namespace{
typedef vector<int> vint;

struct segtree{
	int m;
	vint zeros, delta;
	explicit segtree(int n){
		for(m = 1; m < n; m *= 2);
		zeros.assign(2 * m - 1, 1);
		delta.assign(2 * m - 1, 0);
		delta[0] = 1;
		for(int i = 2 * m - 2; i >= 0; --i){
			eval(i);
		}
	}
	void eval(int k){
		if(delta[k] != 0){
			zeros[k] = 0;
		}
		else if(k >= m - 1){
			zeros[k] = 1;
		}
		else{
			zeros[k] = zeros[k * 2 + 1] + zeros[k * 2 + 2];
		}
	}
	void update(int k, int d){
		delta[k] += d;
		if(k < m - 1){
			int x = min(delta[k * 2 + 1], delta[k * 2 + 2]);
			for(int i = 1; i <= 2; ++i){
				delta[k * 2 + i] -= x;
				eval(k * 2 + i);
			}
			delta[k] += x;
		}
		eval(k);
	}
	void incr(int a, int b, int d){ incr(a, b, d, 0, 0, m); }
	void incr(int a, int b, int d, int k, int l, int r){
		if(b <= l || r <= a){ return; }
		if(a <= l && r <= b){
			update(k, d);
		}
		else{
			delta[k * 2 + 1] += delta[k];
			delta[k * 2 + 2] += delta[k];
			delta[k] = 0;
			incr(a, b, d, k * 2 + 1, l, (l + r) >> 1);
			incr(a, b, d, k * 2 + 2, (l + r) >> 1, r);
			update(k, 0);
		}
	}
	int total(){ return zeros[0]; }
};

vector<vint> tree;
vint par, dpt;
vint szs;
vint seq, rev, fst;

void dfs1(int u, int f){
	rev[u] = seq.size();
	seq.push_back(u);
	fst[u] = f;
	for(int &v : tree[u]){
		if(szs[v] > szs[tree[u][0]]){
			swap(v, tree[u][0]);
		}
	}
	for(size_t i = 0; i < tree[u].size(); ++i){
		int v = tree[u][i];
		dfs1(v, i == 0 ? f : v);
	}
}

void process(segtree &st, int u, int t, int d){
	while(u >= 0 && t >= 0){
		int f = fst[u];
		int g;
		if(dpt[f] >= dpt[u] - t){ g = f; }
		else{
			g = seq[rev[u] - t];
		}
		st.incr(rev[g], rev[u] + 1, d);
		t -= dpt[u] - dpt[f] + 1;
		u = par[f];
	}
}

void solve(){
	int numq, o, f;
	cin >> numq >> o >> f;
	vint qrs(numq, -1);
	tree.emplace_back();
	par.push_back(-1);
	dpt.push_back(0);
	for(int i = 0; i < numq; ++i){
		int tp;
		cin >> tp;
		if(tp == 1){
			cin >> qrs[i];
			int u = tree.size();
			tree.emplace_back();
			tree[qrs[i]].push_back(u);
			par.push_back(qrs[i]);
			dpt.push_back(dpt[qrs[i]] + 1);
		}
	}
	int n = tree.size();
	szs.assign(n, 1);
	for(int i = n - 1; i > 0; --i){
		szs[par[i]] += szs[i];
	}
	rev.assign(n, -1);
	fst.assign(n, -1);
	dfs1(0, 0);

	vector<char> leaf(n, 1);
	segtree sto(n), stf(n);
	int c = 1;
	for(int q : qrs){
		if(q == -1){
			int a = sto.total();
			int b = stf.total();
			cout << (double)(c - a) / (c - b) << '\n';
		}
		else{
			process(sto, q, o - 1, 1);
			process(stf, q, f - 1, 1);
			if(leaf[q]){
				leaf[q] = 0;
				process(sto, q, o, -1);
				process(stf, q, f, -1);
			}
			++c;
		}
	}
}
}

int main(){
	ios::sync_with_stdio(false);
	cout << fixed << setprecision(15);
	solve();
}
accuracy: 1
time_ms: 200
memory_kb: 12600
final_rank: 2