1 条题解
-
0
自动搬运
来自洛谷,原作者为

1saunoya
GoGoGo搬运于
2025-08-24 22:09:14,当前版本为作者最后更新于2020-02-17 15:05:08,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
好妙的一个题…
我们设 为 节点出现 的概率
设 即左儿子右儿子
设 为叶子结点的个数
显然, 出现 的概率为
$$f_{i,j} = f_{l,j} * (p_i \sum_{k=1}^{j-1}f_{r,k} + (1-p_i)\sum_{k=j+1}^{m}f_{r,k}) + f_{r,j} * (p_i \sum_{k=1}^{j-1}f_{l,k} + (1-p_i)\sum_{k=j+1}^{m}f_{l,k}) $$不难发现,这个柿子有关前缀和和后缀和,可以用线段树合并的操作来进行转移,从下到上转移,求出根节点的概率就好了…
#include <cstdio> #include <algorithm> int read() { int x = 0; char c = 0; while (c < 48) c = getchar(); while (c > 47) x = (x << 1) + (x << 3) + (c & 15), c = getchar(); return x; } const int mod = 998244353; int qpow(int x, int y) { int ans = 1; for (; y; y >>= 1, x = 1ll * x * x % mod) if (y & 1) ans = 1ll * ans * x % mod; return ans; } int n; const int maxn = 3e5 + 10; int ch[maxn][2], fa[maxn], cnt[maxn], val[maxn], tmp[maxn], qwq = 0, s[maxn]; int rt[maxn], ls[maxn << 5], rs[maxn << 5], sum[maxn << 5], mul[maxn << 5]; int ans = 0, tot = 0; void pushup(int rt) { sum[rt] = (sum[ls[rt]] +sum[rs[rt]]) % mod; } void pushmul(int rt, int v) { if (!rt) return; sum[rt] = 1ll * sum[rt] * v % mod; mul[rt] = 1ll * mul[rt] * v % mod; } void pushd(int rt) { if (mul[rt] == 1) return; if (ls[rt]) pushmul(ls[rt], mul[rt]); if (rs[rt]) pushmul(rs[rt], mul[rt]); mul[rt] = 1; } int newnode() { int x = ++ tot; ls[x] = rs[x] = sum[x] = 0, mul[x] = 1 ; return x ; } void upd(int& p, int l, int r, int x, int v) { if (!p) p = newnode() ; if (l == r) { sum[p] = v; return; } pushd(p); int mid = l + r >> 1; (x <= mid) ? upd(ls[p], l, mid, x, v) : upd(rs[p], mid + 1, r, x, v); pushup(p); } int merge(int x, int y, int l, int r, int xmul, int ymul, int v) { if (!x && !y) return 0; if (!x) { pushmul(y, ymul); return y; } if (!y) { pushmul(x, xmul); return x; } pushd(x), pushd(y); int mid = l + r >> 1; int lsx = sum[ls[x]], lsy = sum[ls[y]], rsx = sum[rs[x]], rsy = sum[rs[y]]; ls[x] = merge(ls[x], ls[y], l, mid, (xmul + 1ll * rsy % mod * (1 - v + mod)) % mod, (ymul + 1ll * rsx % mod * (1 - v + mod)) % mod, v); rs[x] = merge(rs[x], rs[y], mid + 1, r, (xmul + 1ll * lsy % mod * v) % mod, (ymul + 1ll * lsx % mod * v) % mod, v); pushup(x); return x; } void out(int x, int l, int r) { if (!x) return; if (l == r) { s[l] = sum[x]; return; } int mid = l + r >> 1; pushd(x); out(ls[x], l, mid); out(rs[x], mid + 1, r); } void dfs(int u) { if (!cnt[u]) upd(rt[u], 1, qwq, val[u], 1); if (cnt[u] == 1) dfs(ch[u][0]), rt[u] = rt[ch[u][0]] ; if (cnt[u] == 2) dfs(ch[u][0]), dfs(ch[u][1]), rt[u] = merge(rt[ch[u][0]], rt[ch[u][1]] ,1 , qwq , 0 , 0 , val[u]); } int main() { n = read(); for (int i = 1; i <= n; i++) fa[i] = read(); for (int i = 1; i <= n; i++) if (fa[i]) ch[fa[i]][cnt[fa[i]]++] = i; for (int i = 1; i <= n; i++) val[i] = read(); for (int i = 1; i <= n; i++) { if (cnt[i]) { val[i] = 1ll * val[i] * qpow(10000, mod - 2) % mod; } else { tmp[++qwq] = val[i]; } } std ::sort(tmp + 1, tmp + qwq + 1); for (int i = 1; i <= n; i++) if (!cnt[i]) val[i] = std ::lower_bound(tmp + 1, tmp + qwq + 1, val[i]) - tmp; dfs(1); out(rt[1], 1, qwq); for (int i = 1; i <= qwq; i++) ans = (ans + 1ll * i * tmp[i] % mod * s[i] % mod * s[i]) % mod; printf("%d\n", ans); return 0; }
- 1
信息
- ID
- 4283
- 时间
- 1000ms
- 内存
- 500MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者