题目链接

loj2537

题解

观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率

先离散化一下权值

显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\)的概率

如果\(i\)是叶节点显然

如果\(i\)只有一个儿子直接继承即可

如果\(i\)有两个儿子,对于儿子\(x\),设另一个儿子为\(y\)

则有

\[f[i][j] += f[x][j](1 - p_i)\sum\limits_{k > j}f[r][k] + f[x][j]p_i\sum\limits_{k < j}f[r][k]
\]

直接转移是\(O(n^2)\)的,发现每个节点都有\(O(n)\)个位置需要转移

考虑优化,可以考虑线段树合并

对于一个子树中的权值\(x\),我们记另一棵子树比它大的概率为\(maxa\),

则\(x\)的概率要乘上\(maxa(1 - p_i) + (1 - maxa)p_i = maxa + p_i - 2p_imaxa\)

所以我们在线段树合并过程中,优先合并右子树,并更新两棵子树的\(maxa\)与\(maxb\),就可以在合并过程中转移了

复杂度\(O(nlogn)\)

  1. #include<algorithm>
  2. #include<iostream>
  3. #include<cstring>
  4. #include<cstdio>
  5. #include<cmath>
  6. #include<map>
  7. #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
  8. #define REP(i,n) for (int i = 1; i <= (n); i++)
  9. #define mp(a,b) make_pair<int,int>(a,b)
  10. #define cls(s) memset(s,0,sizeof(s))
  11. #define cp pair<int,int>
  12. #define LL long long int
  13. using namespace std;
  14. const int maxn = 300005,maxm = 8000005,INF = 1000000000,P = 998244353;
  15. inline int read(){
  16. int out = 0,flag = 1; char c = getchar();
  17. while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
  18. while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
  19. return out * flag;
  20. }
  21. int n,Ls[maxn],Rs[maxn],b[maxn],N,v10000;
  22. int rt[maxn],sum[maxm],ls[maxm],rs[maxm],tag[maxm],cnt;
  23. int p[maxn],maxa,maxb;
  24. inline int qpow(int a,int b){
  25. int re = 1;
  26. for (; b; b >>= 1,a = 1ll * a * a % P)
  27. if (b & 1) re = 1ll * re * a % P;
  28. return re;
  29. }
  30. inline void pd(int u){
  31. if (tag[u] > 1){
  32. sum[ls[u]] = 1ll * sum[ls[u]] * tag[u] % P;
  33. sum[rs[u]] = 1ll * sum[rs[u]] * tag[u] % P;
  34. tag[ls[u]] = 1ll * tag[ls[u]] * tag[u] % P;
  35. tag[rs[u]] = 1ll * tag[rs[u]] * tag[u] % P;
  36. tag[u] = 1;
  37. }
  38. }
  39. void modify(int& u,int l,int r,int pos){
  40. u = ++cnt; sum[u] = tag[u] = 1;
  41. if (l == r) return;
  42. int mid = l + r >> 1;
  43. if (mid >= pos) modify(ls[u],l,mid,pos);
  44. else modify(rs[u],mid + 1,r,pos);
  45. }
  46. int merge(int u,int v,int p){
  47. if (!u && !v) return 0;
  48. if (!u){
  49. maxb = (maxb + sum[v]) % P;
  50. int tmp;
  51. tmp = (((maxa + p) % P - 2ll * p * maxa % P) % P + P) % P;
  52. sum[v] = 1ll * sum[v] * tmp % P;
  53. tag[v] = 1ll * tag[v] * tmp % P;
  54. return v;
  55. }
  56. if (!v){
  57. maxa = (maxa + sum[u]) % P;
  58. int tmp;
  59. tmp = (((maxb + p) % P - 2ll * p * maxb % P) % P + P) % P;
  60. sum[u] = 1ll * sum[u] * tmp % P;
  61. tag[u] = 1ll * tag[u] * tmp % P;
  62. return u;
  63. }
  64. pd(u); pd(v);
  65. int t = ++cnt; tag[t] = 1;
  66. rs[t] = merge(rs[u],rs[v],p);
  67. ls[t] = merge(ls[u],ls[v],p);
  68. sum[t] = (sum[ls[t]] + sum[rs[t]]) % P;
  69. return t;
  70. }
  71. void dfs(int u){
  72. if (!Ls[u]) modify(rt[u],1,N,p[u]);
  73. else if (!Rs[u]) dfs(Ls[u]),rt[u] = rt[Ls[u]];
  74. else {
  75. dfs(Ls[u]); dfs(Rs[u]);
  76. maxa = maxb = 0;
  77. rt[u] = merge(rt[Ls[u]],rt[Rs[u]],p[u]);
  78. }
  79. }
  80. int ans;
  81. void cal(int u,int l,int r){
  82. if (l == r) {ans = (ans + 1ll * l * b[l] % P * sum[u] % P * sum[u] % P) % P;return;}
  83. pd(u);
  84. int mid = l + r >> 1;
  85. cal(ls[u],l,mid);
  86. cal(rs[u],mid + 1,r);
  87. }
  88. int main(){
  89. n = read(); read(); int x; v10000 = qpow(10000,P - 2);
  90. for (int i = 2; i <= n; i++){
  91. x = read();
  92. if (!Ls[x]) Ls[x] = i;
  93. else Rs[x] = i;
  94. }
  95. for (int i = 1; i <= n; i++){
  96. p[i] = read();
  97. if (!Ls[i]) b[++N] = p[i];
  98. else p[i] = 1ll * p[i] * v10000 % P;
  99. }
  100. sort(b + 1,b + 1 + N);
  101. for (int i = 1; i <= n; i++)
  102. if (!Ls[i]) p[i] = lower_bound(b + 1,b + 1 + N,p[i]) - b;
  103. dfs(1);
  104. cal(rt[1],1,N);
  105. printf("%d\n",ans);
  106. return 0;
  107. }

loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】的更多相关文章

  1. LOJ2537. 「PKUWC2018」Minimax【概率DP+线段树合并】

    LINK 思路 首先暴力\(n^2\)是很好想的,就是把当前节点概率按照权值大小做前缀和和后缀和然后对于每一个值直接在另一个子树里面算出贡献和就可以了,注意乘上选最大的概率是小于当前权值的部分,选最小 ...

  2. LOJ2537. 「PKUWC2018」Minimax [DP,线段树合并]

    传送门 思路 首先有一个\(O(n^2)\)的简单DP:设\(dp_{x,w}\)为\(x\)的权值为\(w\)的概率. 假设\(w\)来自\(v1\)的子树,那么有 \[ dp_{x,w}=dp_{ ...

  3. 「洛谷4197」「BZOJ3545」peak【线段树合并】

    题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...

  4. loj#2537. 「PKUWC2018」Minimax

    题目链接 loj#2537. 「PKUWC2018」Minimax 题解 设\(f_{u,i}\)表示选取i的概率,l为u的左子节点,r为u的子节点 $f_{u,i} = f_{l,i}(p \sum ...

  5. 「CQOI2006」简单题 线段树

    「CQOI2006」简单题 线段树 水.区间修改,单点查询.用线段树维护区间\([L,R]\)内的所有\(1\)的个数,懒标记表示为当前区间是否需要反转(相对于区间当前状态),下方标记时懒标记取反即可 ...

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

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

  7. 【LOJ】#2537. 「PKUWC2018」Minimax

    题解 加法没写取模然后gg了QwQ,de了半天 思想还是比较自然的,线段树合并的维护方法我是真的很少写,然后没想到 很显然,我们有个很愉快的想法是,对于每个节点枚举它所有的叶子节点,对于一个叶子节点的 ...

  8. 「PKUWC2018」Minimax

    题面 题解 强势安利一波巨佬的$blog$ 线段树合并吼题啊 合并的时候要记一下$A$点权值小于$l$的概率和$A$点权值大于$r$的概率,对$B$点同样做 时空复杂度$\text O(nlogw)$ ...

  9. [PKUWC2018]Minimax [dp,线段树合并]

    好妙的一个题- 我们设 \(f_{i,j}\) 为 \(i\) 节点出现 \(j\) 的概率 设 \(l = ch[i][0] , r = ch[i][1]\) 即左儿子右儿子 设 \(m\) 为叶子 ...

随机推荐

  1. Laya资源加载小记

    Laya.Loader负责资源的加载逻辑,被LoaderManager管理. Laya支持多种类型资源加载,也支持自定义类型加载.不同类型的加载方式可能不同. Laya.Loader缓存已经被加载过得 ...

  2. linux文件种类及其扩展名

    文件种类 普通文件(ls -al出来第一列为-) 纯文本文件(ASCII):linux系统中最多的一种文件类型,可以使用cat直接读取: 二进制文件(binary):linux下面的可执行文件: 数据 ...

  3. GIT问题(二)——add报错

  4. Trait 是什么东西

    PHP官方手册里面写的内容是 自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.Trait 为了减少 ...

  5. printf命令详解

    基础命令学习目录首页 本文是Linux Shell系列教程的第(八)篇,更多shell教程请看:Linux Shell系列教程 在上一篇:Linux Shell系列教程之(七)Shell输出这篇文章中 ...

  6. Beta阶段版本控制报告

    版本控制代码及文档要求 在coding.net版本控制; 公开项目,教师.专家.其他同学可以不注册源代码.在此公布git地址. 报告beta阶段2周中,项目的版本控制情况,不包括未在coding.ne ...

  7. 第十章I/O

    系统级i/o 开始进程时的三个标准: 标准输入(描述符0):STDIN_FILENO 标准输出(描述符1):STDOUT_FILENO 标准错误(描述符2):STDERR_FILENO 文件位置: 从 ...

  8. web07-jdbcBookStore

    新建web项目,名字 新建servlet,名字CreateDBServlet 内容为: ---- 配置web.xml 数据库的URL.driveclass.user.passWord都写在web.xm ...

  9. Hibernate 与 mybatis 区别

    JAVA面试中问及HIBERNATE与 MYBATIS的对比,在这里做一下总结   我是一名java开发人员,hibernate以及mybatis都有过学习,在java面试中也被提及问道过,在项目实践 ...

  10. 文件上传到tomcat服务器 commons-fileupload的详细介绍与使用

    三个类:DiskFileUpload.FileItem和FileUploadException.这三个类全部位于org.apache.commons.fileupload包中. 首先需要说明一下for ...