先考虑不掺金坷垃的做法。

设猴子处于 \(i\) 节点的概率为 \(f_i\),列出方程如下(\(i\) 的祖先包括自身):

\[f_i = \sum_{j为i祖先}\frac{1-p_j}{siz_j}f_j + \sum_{(i,j)}p_jf_j \\
\sum f_i = 1
\]

可以 \(O(n^3)\) 暴力高消。但是并没有用到树上高消的性质。

考虑到枚举祖先不太优,可以将 \(f_i\) 做前缀和:

\[F_i = \sum_{j为i祖先}\frac{1-p_j}{siz_j}f_j \\
f_i = \frac{siz_i}{1-p_i}(F_i-F_{fa})
\]

代入上式:

\[\frac{siz_i}{1-p_i}(F_i-F_{fa}) = \sum_{(i,j)}p_j\frac{siz_j}{1-p_j}(F_j-F_i) + F_i \\
\left( \frac{siz_i}{1-p_i} + \sum_{(i,j)}p_j\frac{siz_j}{1-p_j} - 1 \right)F_i =
\left( \frac{siz_i}{1-p_i} \right)F_{fa} +
\sum_{(i,j)}p_j\frac{siz_j}{1-p_j}F_j
\]
\[\begin{aligned}
A_i &= \frac{siz_i}{1-p_i} + \sum_{(i,j)}p_j\frac{siz_j}{1-p_j} - 1 \\
B_i &= \frac{siz_i}{1-p_i} \\
C_i &= \sum_{(i,j)}p_j\frac{siz_j}{1-p_j}F_j \\
A_iF_i &= B_iF_{fa} + C_i
\end{aligned}
\]

令 \(q_i = \frac{siz_i}{1-p_i}\)。

从叶子往根求出对于每个 \(i\),\(F_i = k_iF_{fa}+b_i\),即 \(F_j=k_jF_i+b_j\):

\[\begin{aligned}
C_i &= \sum_{(i,j)}p_j\frac{siz_j}{1-p_j}F_j \\
&= \sum_{(i,j)}p_jq_j(k_jF_i+b_j) \\
&= F_i\sum_{(i,j)}p_jq_jk_j + \sum_{(i,j)}p_jq_jb_j \\
\end{aligned}
\]
\[Sk_i = \sum_{(i,j)}p_jq_jk_j \\
Sb_i = \sum_{(i,j)}p_jq_jb_j
\]
\[\therefore (A_i-Sk_i)F_i = B_iF_{fa} + Sb_i \\
F_i = \cfrac{B_i}{A_i-Sk_i}F_{fa} + \cfrac{Sb_i}{A_i-Sk_i} \\
\begin{cases}
k_i = \cfrac{B_i}{A_i-Sk_i} \\
b_i = \cfrac{Sb_i}{A_i-Sk_i} \\
\end{cases}
\]

求出来每个节点的 \(k_i\) 后,从根开始 \(dfs\) 一遍,算出 \(F_i\) 相对于 \(F_{rt}\) 的系数,进而差分求出 \(f_i\) 相对于 \(f_{rt}\) 的系数。

代入 \(\sum f_i = 0\) 的方程,求解出 \(f_{rt}\),进而求解出所有的 \(f\) 值。答案就是 \(\sum p_if_i\)。

同时发现对于叶子结点,\(b_i=0\),所以对于所有节点,\(b_i\) 均为 \(0\),计算时可以不考虑 \(b_i\)。

掺了金坷垃以后(一袋能顶两代撒),考虑到必有一个新节点的 \(p_i=0\),也就是说,一旦跳入了其子树就不会再跳出来。而时间无穷大,可以不考虑子树外的贡献,只需计算子树内的期望即可。

总的时间复杂度就是 \(O(\sum siz_i)\),由于树的形态随机,期望时间复杂度为 \(O(n \log n)\)。

/**
* @file: UOJ96.cpp
* @author: yaoxi-std
* @url: https://uoj.ac/problem/96
*/
// #pragma GCC optimize ("O2")
// #pragma GCC optimize ("Ofast", "inline", "-ffast-math")
// #pragma GCC target ("avx,sse2,sse3,sse4,mmx")
#include <bits/stdc++.h>
using namespace std;
#define debug(fmt, ...) \
fprintf(stderr, "[%s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
using ll = long long;
const int MAXN = 5e5 + 10;
const int INF = 0x3f3f3f3f;
int n, dfc, a[MAXN], fa[MAXN], dfn[MAXN], siz[MAXN];
double p[MAXN], q[MAXN], k[MAXN], f[MAXN];
vector<int> son[MAXN];
void dfs(int u) {
siz[dfn[u] = ++dfc] = 1;
for (auto v : son[u]) dfs(v), fa[dfn[v]] = dfn[u], siz[dfn[u]] += siz[dfn[v]];
}
double work(int u) {
const int L = u, R = u + siz[u] - 1;
for (int i = L; i <= R; ++i) {
p[i] = (i == 1 ? 0 : (a[i] + n - a[u]) % n * 1.0 / n);
q[i] = siz[i] / (1 - p[i]), k[i] = q[i] - 1;
}
for (int i = R; i >= L + 1; --i) k[i] = q[i] / k[i], k[fa[i]] -= p[i] * q[i] * (k[i] - 1);
double sumk = 0, ret = 0; k[u] = f[u] = 1;
for (int i = L + 1; i <= R; ++i) k[i] *= k[fa[i]], f[i] = k[i] - k[fa[i]];
for (int i = L; i <= R; ++i) sumk += (f[i] *= q[i]);
for (int i = L; i <= R; ++i) ret += f[i] * (1 / sumk) * p[i];
return ret;
}
signed main() {
scanf("%d%d", &n, &fa[1]);
for (int i = 2; i <= n; ++i) scanf("%d", &fa[i]), son[fa[i]].push_back(i);
double ans = 0; dfs(1);
for (int i = 1; i <= n; ++i) scanf("%d", &a[dfn[i]]);
for (int i = 1; i <= n; ++i) ans = max(ans, work(i));
return printf("%.9lf\n", ans), 0;
}

[UOJ96] 【集训队互测2015】胡策的小树的更多相关文章

  1. 【uoj#94】【集训队互测2015】胡策的统计(集合幂级数)

    题目传送门:http://uoj.ac/problem/94 这是一道集合幂级数的入门题目.我们先考虑求出每个点集的连通生成子图个数,记为$g_S$,再记$h_S$为点集$S$的生成子图个数,容易发现 ...

  2. 【集训队互测2015】Robot

    题目描述 http://uoj.ac/problem/88 题解 维护两颗线段树,维护最大值和最小值,因为每次只有单点查询,所以可以直接在区间插入线段就可以了. 注意卡常,不要写STL,用链表把同类修 ...

  3. BZOJ3938 & UOJ88:[集训队互测2015]Robot——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=3938 http://uoj.ac/problem/88 小q有n只机器人,一开始他把机器人放在了一 ...

  4. 【loj2461】【2018集训队互测Day 1】完美的队列

    #2461. 「2018 集训队互测 Day 1」完美的队列 传送门: https://loj.ac/problem/2461 题解: 直接做可能一次操作加入队列同时会弹出很多数字,无法维护:一个操作 ...

  5. 【2018集训队互测】【XSY3372】取石子

    题目来源:2018集训队互测 Round17 T2 题意: 题解: 显然我是不可能想出来的……但是觉得这题题解太神了就来搬(chao)一下……Orzpyz! 显然不会无解…… 为了方便计算石子个数,在 ...

  6. 洛谷 P4463 - [集训队互测 2012] calc(多项式)

    题面传送门 & 加强版题面传送门 竟然能独立做出 jxd 互测的题(及其加强版),震撼震撼(((故写题解以祭之 首先由于 \(a_1,a_2,\cdots,a_n\) 互不相同,故可以考虑求出 ...

  7. UOJ#191. 【集训队互测2016】Unknown 点分治 分治 整体二分 凸包 计算几何

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ191.html 题目传送门 - UOJ191 题意 自行移步集训队论文2016中罗哲正的论文. 题解 自行 ...

  8. LOJ3069. 「2019 集训队互测 Day 1」整点计数(min_25筛)

    题目链接 https://loj.ac/problem/3069 题解 复数真神奇. 一句话题意:令 \(f(x)\) 表示以原点 \((0, 0)\) 为圆心,半径为 \(x\) 的圆上的整点数量, ...

  9. UOJ#191. 【集训队互测2016】Unknown

    题意:维护一个数列,每个元素是个二维向量,每次可以在后面加一个元素或者删除一个元素.给定P(x,y),询问对于[l,r]区间内的元素$S_i$,$S_i \times P$的最大值是多少. 首先简单地 ...

随机推荐

  1. C++ 右值引用与一级指针

    将右值引用用于一级指针,在初始化时等号右边必须为右值,有以下几种用法: //方式一:引用一级指针,常规用法 int a = 5; int * &&rrpa = &a; //右值 ...

  2. 2022-08-14-esp32把玩记-③_轻轻松松显示个二维码(esp32+ssd1306显示图片)

    layout: post cid: 9 title: esp32把玩记-③ 轻轻松松显示个二维码(esp32+ssd1306显示图片) slug: 9 date: 2022/08/14 09:22:0 ...

  3. 安装与配置FTP服务器

    概:   文件传输协议 (File Transfer Protocol,FTP),用于在网络上进行文件传输的协议.如果用户需要将文件从本机发送到另一台计算机,可以使用FTP上传操作:反之,用户可以使用 ...

  4. 虚拟机安装Linux系统的网络配置

    1. 进入配置文件配置.如果不知道ifcfg 后的内容.使用ifconfig vi /etc/sysconfig/network-scripts/ifcfg-ens33 如果不知道网关怎样配置就找到这 ...

  5. JUC(7)四大函数式接口

    文章目录 1.四大函数式接口(必须掌握) 1.1 function 1.2 Predicate 1.3 Consumer 1.4 Supplier 1.四大函数式接口(必须掌握) 1.lambda表达 ...

  6. VScode将代码提交到远程服务器、同时解决每次提交都要输入密码的问题(这里以gitee为例子)

    文章目录 1.第一种情况.项目直接从gitee上拉取下来 2.第二种情况.将新建的项目提交到远程服务器 3.解决将代码提交到远程每次都要输入用户名和密码 4.个人遇到的奇葩问题 1.第一种情况.项目直 ...

  7. el-select实现下拉框触底加载更多

    当下拉框需要展示的数据有很多时,几千甚至上万条,一次性全部请求回来再按照特定格式比如 id-name 去处理数据的话,不论是从接口还是前端,这个性能都不是很好,会造成下拉框初次打开时响应很慢,影响用户 ...

  8. 嵌入式-C语言基础:指针

    指针就是地址,变量的值可以通过两种方式访问,一个是通过变量名,一个是通过地址访问. 从而引出一个问题,即什么是指针变量?整型(字符)变量就是存放整形(字符)的变量,指针变量就是存放指针的变量,也就是存 ...

  9. DevExpress窗体加载等待

    using DevExpress.XtraEditors; using DevExpress.XtraSplashScreen; using System; using System.Collecti ...

  10. 2022春每日一题:Day 14

    题目:字符串归类 发现字符串长度总数不大,因此把每个字符串有的字母分离,存放到桶中,再枚举合并即可,时间复杂度O(len) 赛时代码: #include <cstdio> #include ...