Luogu5298 [PKUWC2018]Minimax

太久没写博客了,过来水一发。感觉自己推式子的功力还不够。。。

题目链接:洛谷


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

假设现在是$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$的前/后缀和也可以放在参数里面顺便维护了。

 1 #include<bits/stdc++.h>
 2 #define Rint register int
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 300003, mod = 998244353, inv = 796898467;
 6 int n, v[N], tot, p[N], fa[N], head[N], to[N], nxt[N];
 7 inline void add(int a, int b){
 8     static int cnt = 0;
 9     to[++ cnt] = b; nxt[cnt] = head[a]; head[a] = cnt;
10 }
11 int root[N], ls[N << 5], rs[N << 5], seg[N << 5], tag[N << 5], cnt, ans;
12 inline void pushdown(int x){
13     if(x && tag[x] != 1){
14         if(ls[x]){
15             seg[ls[x]] = (LL) seg[ls[x]] * tag[x] % mod;
16             tag[ls[x]] = (LL) tag[ls[x]] * tag[x] % mod;
17         }
18         if(rs[x]){
19             seg[rs[x]] = (LL) seg[rs[x]] * tag[x] % mod;
20             tag[rs[x]] = (LL) tag[rs[x]] * tag[x] % mod;
21         }
22         tag[x] = 1;
23     }
24 }
25 inline void change(int &x, int L, int R, int pos){
26     if(!x) tag[x = ++ cnt] = 1;
27     pushdown(x);
28     ++ seg[x];
29     if(seg[x] >= mod) seg[x] = 0;
30     if(L == R) return;
31     int mid = L + R >> 1;
32     if(pos <= mid) change(ls[x], L, mid, pos);
33     else change(rs[x], mid + 1, R, pos);
34 }
35 inline int merge(int lx, int rx, int L, int R, int pl, int pr, int sl, int sr, int P){
36     if(!lx && !rx) return 0;
37     int now = ++ cnt, mid = L + R >> 1; tag[now] = 1;
38     pushdown(lx); pushdown(rx);
39     if(!lx){
40         int v = ((LL) P * sl + (mod + 1ll - P) * sr) % mod;
41         seg[now] = (LL) seg[rx] * v % mod;
42         tag[now] = (LL) tag[rx] * v % mod;
43         ls[now] = ls[rx]; rs[now] = rs[rx];
44         return now;
45     }
46     if(!rx){
47         int v = ((LL) P * pl + (mod + 1ll - P) * pr) % mod;
48         seg[now] = (LL) seg[lx] * v % mod;
49         tag[now] = (LL) tag[lx] * v % mod;
50         ls[now] = ls[lx]; rs[now] = rs[lx];
51         return now;
52     }
53     ls[now] = merge(ls[lx], ls[rx], L, mid, pl, (pr + seg[rs[rx]]) % mod, sl, (sr + seg[rs[lx]]) % mod, P);
54     rs[now] = merge(rs[lx], rs[rx], mid + 1, R, (pl + seg[ls[rx]]) % mod, pr, (sl + seg[ls[lx]]) % mod, sr, P);
55     seg[now] = (seg[ls[now]] + seg[rs[now]]) % mod;
56     return now;
57 }
58 inline void getans(int x, int L, int R){
59     pushdown(x);
60     if(L == R){
61         ans = (ans + (LL) seg[x] * seg[x] % mod * v[L] % mod * L % mod) % mod;
62         return;
63     }
64     int mid = L + R >> 1;
65     getans(ls[x], L, mid);
66     getans(rs[x], mid + 1, R);
67 }
68 inline void dfs(int x){
69     if(!head[x]){
70         change(root[x], 1, n, p[x]);
71         return;
72     }
73     for(Rint i = head[x];i;i = nxt[i]){
74         dfs(to[i]);
75         if(!root[x]) root[x] = root[to[i]];
76         else root[x] = merge(root[x], root[to[i]], 1, n, 0, 0, 0, 0, p[x]);
77     }
78 }
79 int main(){
80     scanf("%d", &n);
81     for(Rint i = 1;i <= n;i ++){
82         scanf("%d", fa + i);
83         if(fa[i]) add(fa[i], i);
84     }
85     for(Rint i = 1;i <= n;i ++){
86         scanf("%d", p + i);
87         if(head[i]) p[i] = (LL) p[i] * inv % mod;
88         else v[++ tot] = p[i];
89     }
90     sort(v + 1, v + tot + 1);
91     for(Rint i = 1;i <= n;i ++)
92         if(!head[i]) p[i] = lower_bound(v + 1, v + tot + 1, p[i]) - v;
93     dfs(1);
94     getans(root[1], 1, n);
95     printf("%d", ans);
96 }
luogu5369

 

转载于:https://www.cnblogs.com/AThousandMoons/p/10893829.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/362630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js实现类名的添加与移除

方法1&#xff1a;使用className属性&#xff1b; 方法2&#xff1a;使用classList API&#xff1b; //用于匹配类名存在与否 function reg(name){return new RegExp((^|\\s) name (\\s |$)); }//hasClass addClass removeClass toogleClass var hasClass,addClass,removeCla…

js封装常用函数

自己封装函数时&#xff0c;参数最好不要超过3个&#xff0c;若要超过&#xff0c;可以用数组或者对象&#xff1b; 1. 利用&#xff08;Math.random&#xff09;写指定范围的随机数 2. 补零 3. 数组去重 4. 排序 5. 敏感词过滤 6. 判断数组中是否存在某一条数据&#xff0c;结…

redis学习(一)

1.redis安装&#xff08;来自 https://www.runoob.com/redis/redis-install.html&#xff09; window下安装 下载地址&#xff1a;https://github.com/MSOpenTech/redis/releases。 Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择&#xff0c;这里我们下载 R…

多项式相加链表

#include <stdio.h> #include <stdlib.h> typedef struct Node //一个项节点 { int modulus; //系数 int cover; //幂 struct Node* next; }List; void creatList(List *&l) //创建多项式链表 { List* r; List* s; int n; l (List*)malloc(sizeof(Node)); r …

JPA教程–在Java SE环境中设置JPA

JPA代表Java Persistence API&#xff0c;它基本上是一个规范&#xff0c;描述了一种将数据持久存储到持久存储&#xff08;通常是数据库&#xff09;中的方法。 我们可以将其视为类似于Hibernate的 ORM工具的东西&#xff0c;除了它是Java EE规范的正式组成部分&#xff08;并…

h5上传图片及预览

第一次做图片上传&#xff0c;记录一些问题。 1&#xff0c;图片的base64编码就是可以将一副图片数据编码成一串字符串&#xff0c;使用该字符串代替图像地址。而网页上的每一个图片&#xff0c;都是需要消耗一个http请求下载而来的&#xff0c;使用base64就不用请求http。 2&a…

JSON(一)

JSON&#xff1a;JavaScript Object Notation(JavaScript 對象表示法&#xff09; JSON是存儲和交換文本信息的語法。類似于XML。 JSON比XML更小&#xff0c;更快&#xff0c;更易解析。 什麼是JSON &#xff1f; JSON指的是JavaScript對象表示法 是輕量級的文本數據交換格式…

滚动条造成页面抖动问题

总结&#xff1a; 若用到 margin:0 auto; 使页面居中&#xff0c;若部分页面出现滚动条&#xff0c;滚动条默认有 20px&#xff0c;这样会造成页面抖动&#xff1b; 解决办法&#xff1a;参考 1. html{overflow:scoll;} 让页面一直显示滚动条。 overflow 的几个属性值&#xf…

编写数据访问代码测试–单元测试是浪费

几年前&#xff0c;我是为我的数据访问代码编写单元测试的那些开发人员之一。 我正在孤立地测试所有内容&#xff0c;我对自己感到非常满意。 老实说&#xff0c;我认为自己做得很好。 哦&#xff0c;男孩&#xff0c;我错了&#xff01; 这篇博客文章描述了为什么我们不应该为…

[JSON].typeOf( keyPath )

语法&#xff1a;[JSON].typeOf( keyPath ) 返回&#xff1a;[String | Number | Boolean | Json | Array | Function | 空字符] 说明&#xff1a;获取指定键名值的类型 示例&#xff1a; Set jsonObj toJson("{a: test, b: 1, c:true, d:[1,2,3,4], e:{a1:2}}"…

简单电商购物程序

sum0i1""shuruinput("请输入“手机”或“电脑”&#xff1a;")if shuru"手机": while True: sp{"iphoneX"7998,"华为P30"6998} print(sp) ainput("输入Buy进入结算,继续购买请输入物品名称&#xff1a;") if i&qu…

ie 浏览器布局中的 offset

出现原因&#xff1a; 此处的offset的值表示的是盒子模型经过计算后的实际偏移量&#xff0c;通常是margin及定位偏移量之和&#xff08;flex布局导致的偏移也会计算在内&#xff09;。在此处也无需消除。 解决办法&#xff1a; 父元素设置宽高。设置margin为负数&#xff0…

【Set jsonObj = toJson( jsonString )】创建JSON实例

创建JSON实例&#xff1a; 原型: toJson( jsonString ) 说明: 创建JSON实例 返回: [JSON] 参数:jsonString [可选] 可以用json格式字符串创建实例 示例&#xff1a; <% 方法一&#xff1a;创建一个空的JSON实例 Set jsonObj1 toJson() 方法二&#xff1a;用JSON字符串创建…

当我们的代码遇到问题的时候....;要想不遇到问题,写代码的时候要.....

当我们的代码遇到问题的时候&#xff1a;1&#xff0c;不要怨天怨地。出了问题&#xff0c;当然有可能是系统的bug&#xff0c;API的问题&#xff0c;但是那些几率往往比你犯低级错误的几率要低多了&#xff0c;先从自己身上找原因&#xff0c;是不是自己写错了。   2&#x…

为什么我不信任通配符,以及为什么我们仍然需要通配符

在将子类型多态性&#xff08;面向对象&#xff09;与参数多态性&#xff08;泛型&#xff09;相结合的任何编程语言中&#xff0c;都会出现方差问题。 假设我有一个字符串列表&#xff0c;键入List<String> 。 我可以将其传递给接受List<Object>的函数吗&#xff…

MySQL集群(PXC)入门

一、学习动机 伴随互联网行业的兴起&#xff0c;越来越多的领域需要相应的技术方案&#xff0c;比如&#xff1a;打出软件、电商平台、直播平台、电子支付、媒体社交。 身边常见的&#xff0c;校园出成绩那一年&#xff0c;我们会感觉网站异常的卡顿&#xff0c;因为访问人数太…

滚动条那些事

一、滚动条样式 1. ie8浏览器 名称描述scrollbar-arrow-color三角箭头的颜色scrollbar-face-color立体滚动条的颜色&#xff08;包括箭头部分的背景色&#xff09;scrollbar-3dlight-color立体滚动条亮边的颜色scrollbar-highlight-color滚动条的高亮颜色&#xff08;左阴影&…

【自定义组件】如何引用自定义组件

1. 可以在APP.JSON内引用自定义组件&#xff0c;此时该组件为所有页面共享。 2. 可以在页面的JSON文件内引用自定义组件&#xff0c;此时为该页面独享。 引入代码如下&#xff1a; /** * myTag 自定义组件名称 * path/to/the/custom/component 自定义组件所在路径 **/ {"…

Javascript高级程序设计第二版第十四章--异常--笔记

chaepter 14 错误异常分享。 其实主要是就是try{}catch(error){} finally{}这个语句的理解。主要一点&#xff1a;finally 在 return 之后 运行。这跟java里边的如出一辙。 比如&#xff1a;try{return1;}catch(error){return2;} finally{return0;}返回 return 0;然后接着就是 …

Java并发教程–原子性和竞争条件

原子性是多线程程序中的关键概念之一。 我们说一组动作是原子的&#xff0c;如果它们都以不可分割的方式作为一个单一的操作执行。 认为多线程程序中的一组操作将被串行执行是理所当然的&#xff0c;可能会导致错误的结果。 原因是由于线程干扰&#xff0c;这意味着如果两个线程…