太久没写博客了,过来水一发。

题目链接:洛谷


首先我们想到,考虑每个叶节点的权值为根节点权值的概率。首先要将叶节点权值离散化。

假设现在是$x$节点,令$f_i,g_i$分别表示左/右节点的权值$=i$的概率。

若$w_x$来自于左儿子,则

$$P(w_x=i)=f_i*(p_x*\sum_{j=1}^{i-1}g_j+(1-p)*\sum_{j=i+1}^mg_j)$$

右儿子也是一样的。

所以在转移的时候需要顺便维护$f,g$的前/后缀和。

但是我们发现这样直接跑是$O(n^2)$的,肯定不行,但是每个节点的所有dp值都只依赖于两个儿子,而且区间乘法是可以使用lazy_tag的,所以可以使用线段树合并

(等会儿,好像之前并没有写过。。。)

线段树合并就是对于值域线段树,合并的时候如果两棵树都有这个节点,那么就递归下去,否则直接按照上面的式子转移。

$f,g$的前/后缀和也可以放在参数里面顺便维护了。

 #include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = , mod = , inv = ;
int n, v[N], tot, p[N], fa[N], head[N], to[N], nxt[N];
inline void add(int a, int b){
static int cnt = ;
to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
}
int root[N], ls[N << ], rs[N << ], seg[N << ], tag[N << ], cnt, ans;
inline void pushdown(int x){
if(x && tag[x] != ){
if(ls[x]){
seg[ls[x]] = (LL) seg[ls[x]] * tag[x] % mod;
tag[ls[x]] = (LL) tag[ls[x]] * tag[x] % mod;
}
if(rs[x]){
seg[rs[x]] = (LL) seg[rs[x]] * tag[x] % mod;
tag[rs[x]] = (LL) tag[rs[x]] * tag[x] % mod;
}
tag[x] = ;
}
}
inline void change(int &x, int L, int R, int pos){
if(!x) tag[x = ++ cnt] = ;
pushdown(x);
++ seg[x];
if(seg[x] >= mod) seg[x] = ;
if(L == R) return;
int mid = L + R >> ;
if(pos <= mid) change(ls[x], L, mid, pos);
else change(rs[x], mid + , R, pos);
}
inline int merge(int lx, int rx, int L, int R, int pl, int pr, int sl, int sr, int P){
if(!lx && !rx) return ;
int now = ++ cnt, mid = L + R >> ; tag[now] = ;
pushdown(lx); pushdown(rx);
if(!lx){
int v = ((LL) P * sl + (mod + 1ll - P) * sr) % mod;
seg[now] = (LL) seg[rx] * v % mod;
tag[now] = (LL) tag[rx] * v % mod;
ls[now] = ls[rx]; rs[now] = rs[rx];
return now;
}
if(!rx){
int v = ((LL) P * pl + (mod + 1ll - P) * pr) % mod;
seg[now] = (LL) seg[lx] * v % mod;
tag[now] = (LL) tag[lx] * v % mod;
ls[now] = ls[lx]; rs[now] = rs[lx];
return now;
}
ls[now] = merge(ls[lx], ls[rx], L, mid, pl, (pr + seg[rs[rx]]) % mod, sl, (sr + seg[rs[lx]]) % mod, P);
rs[now] = merge(rs[lx], rs[rx], mid + , R, (pl + seg[ls[rx]]) % mod, pr, (sl + seg[ls[lx]]) % mod, sr, P);
seg[now] = (seg[ls[now]] + seg[rs[now]]) % mod;
return now;
}
inline void getans(int x, int L, int R){
pushdown(x);
if(L == R){
ans = (ans + (LL) seg[x] * seg[x] % mod * v[L] % mod * L % mod) % mod;
return;
}
int mid = L + R >> ;
getans(ls[x], L, mid);
getans(rs[x], mid + , R);
}
inline void dfs(int x){
if(!head[x]){
change(root[x], , n, p[x]);
return;
}
for(Rint i = head[x];i;i = nxt[i]){
dfs(to[i]);
if(!root[x]) root[x] = root[to[i]];
else root[x] = merge(root[x], root[to[i]], , n, , , , , p[x]);
}
}
int main(){
scanf("%d", &n);
for(Rint i = ;i <= n;i ++){
scanf("%d", fa + i);
if(fa[i]) add(fa[i], i);
}
for(Rint i = ;i <= n;i ++){
scanf("%d", p + i);
if(head[i]) p[i] = (LL) p[i] * inv % mod;
else v[++ tot] = p[i];
}
sort(v + , v + tot + );
for(Rint i = ;i <= n;i ++)
if(!head[i]) p[i] = lower_bound(v + , v + tot + , p[i]) - v;
dfs();
getans(root[], , n);
printf("%d", ans);
}

luogu5369

Luogu5298 [PKUWC2018]Minimax的更多相关文章

  1. BZOJ5461: [PKUWC2018]Minimax

    BZOJ5461: [PKUWC2018]Minimax https://lydsy.com/JudgeOnline/problem.php?id=5461 分析: 写出\(dp\)式子:$ f[x] ...

  2. 题解-PKUWC2018 Minimax

    Problem loj2537 Solution pkuwc2018最水的一题,要死要活调了一个多小时(1h59min) 我写这题不是因为它有多好,而是为了保持pkuwc2018的队形,与这题类似的有 ...

  3. [PKUWC2018] Minimax

    Description 给定一棵 \(n\) 个节点的树,每个节点最多有两个子节点. 如果 \(x\) 是叶子,则给定 \(x\) 的权值:否则,它的权值有 \(p_x\) 的概率是它子节点中权值的较 ...

  4. BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)

    BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...

  5. LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并

    传送门 题意:自己去看 首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的. 所以我们只需要考虑每一个值的取到的概率. 很容易设计出一个$DP$:设$f_{i,j}$为在第$ ...

  6. LOJ2537:[PKUWC2018]Minimax——题解

    https://loj.ac/problem/2537 参考了本题在网上能找到的为数不多的题解. 以及我眼睛瞎没看到需要离散化,还有不开longlong见祖宗. ——————————————————— ...

  7. [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)

    还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...

  8. 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)

    点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...

  9. Luogu P5298 [PKUWC2018]Minimax

    好劲的题目啊,根本没往线段树合并方面去想啊 首先每种权值都有可能出现,因此我们先排个序然后一个一个求概率 由于此时数的值域变成\([1,m]\)(离散以后),我们可以设一个DP:\(f_{x,i}\) ...

随机推荐

  1. win7+cuda+anaconda python+tensorflow-gpu+keras安装成功版本匹配汇总

    win7+cuda+anaconda python+tensorflow-gpu+keras安装成功版本匹配汇总 2019-09-20 15:06:03 wyx100 阅读数 38更多 分类专栏: M ...

  2. outlook 升级 及邮件同步方式设置

    **office(outlook2010 32B)升级到office2016 64B时的操作 1.删除office(excel. word等) 2.选择offcie2016 安装程序安装 (outlo ...

  3. Myatis之bind标签

    myBatis的bind的标签,一般的用法都是 <if test="name!= null and name!= '' "> <bind name="u ...

  4. JDBC 学习复习10 编写自己的JDBC框架

    首先万分感谢狼哥 孤傲苍狼 博客,整个jdbc学习的博客资料 链接为http://www.cnblogs.com/xdp-gacl/p/4006830.html 详细代码见狼哥博客,列出我学习过程中遇 ...

  5. Django入门第一步:构建一个简单的Django项目

    Django入门第一步:构建一个简单的Django项目 1.简介 Django是一个功能完备的Python Web框架,可用于构建复杂的Web应用程序.在本文中,将通过示例跳入并学习Django.您将 ...

  6. 面试题之String s="a"+"b"+"c"+"d";

    今天遇到了一个面试题的选择,我当时真的没怎么在意,其实挺好玩的. 1.这条语句String s="a"+"b"+"c"+"d&qu ...

  7. 【外网不好用】可以尝试添加dns即可解决上不去外网的问题。

    可以将IPv4这里的DNS修改成以下内容再尝试上网试试.

  8. laravel 的安装与配置

    1.工作环境 php 7.0+ .MySQL5.1+ 这里可以用开发环境包一键安装: 自己用的是wamp(windows)http://www.wampserver.com/en/ linux系统和m ...

  9. 如何用SAP WebIDE的Fiori创建向导基于ABAP OData service快速创建UI5应用

    如果我们手上已经有可以正常工作的OData服务,无论位于ABAP on-premise系统还是public上的internet OData service,都可以用SAP WebIDE里的Fiori创 ...

  10. JLINK固件烧写

    最近在使用uVision V5.14.0.0 的时候,由于我使用的Jlink是盗版的,导致软件总是退出,然后再网上找到了解决办法. 下面介绍解决办法: 参考: http://www.9mcu.com/ ...