[PKUWC2018] Minimax

时间:2021-10-23 08:51:41

Description

给定一棵 \(n\) 个节点的树,每个节点最多有两个子节点。

如果 \(x\) 是叶子,则给定 \(x\) 的权值;否则,它的权值有 \(p_x\) 的概率是它子节点中权值的较大值,\(1-p_x\) 的概率是它子节点中权值的较小值。保证叶子结点权值互不相同。

求根节点所有可能的权值的概率。模 \(998244353\)。

Solution

嗯比较自然的一道题。

设 \(f_{i,x}\) 为结点 \(i\) 权值为 \(x\) 的概率,\(l,r\) 分别是点 \(i\) 的左右子树,则有(假设权值 \(x\) 在 \(l\) 中出现):

\[f_{i,x}=\sum_{j=1}^{x-1}f_{l,x}\cdot f_{r,j}\cdot p_i+\sum_{j=x+1}^n f_{i,x}\cdot f_{r,j}\cdot (1-p_i)
\]

发现这上是一个合并的过程,可以拿线段树合并做。

中间维护两棵树的前缀和后缀和,以及打好标记即可。

Code

LOJ格式化代码真好玩

我能玩一天

放上被LOJ格式化之后的代码

#include <bits/stdc++.h>
using std::max;
using std::min;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int, int>
#define all(A) A.begin(), A.end()
#define mp(A, B) std::make_pair(A, B)
#define int long long
const int N = 3e5 + 5;
const int M = N * 20;
const int mod = 998244353; int sum[M], flag[M], inv;
int val[N], g[N], is[N], ans;
int n, cnt, leaf, head[N], lef;
int ch[M][2], tot, len, rt[N]; struct Edge {
int to, nxt;
} edge[N << 1]; #define ls ch[x][0]
#define rs ch[x][1] void pushup(int x) { sum[x] = (sum[ls] + sum[rs]) % mod; } void pushdown(int x) {
if (flag[x] != 1) {
(flag[ls] *= flag[x]) %= mod;
(flag[rs] *= flag[x]) %= mod;
(sum[ls] *= flag[x]) %= mod;
(sum[rs] *= flag[x]) %= mod;
flag[x] = 1;
}
} void modify(int &x, int l, int r, int ql) {
x = ++tot;
flag[x] = 1;
if (l == r)
return sum[x] = 1, void();
int mid = l + r >> 1;
ql <= mid ? modify(ls, l, mid, ql) : modify(rs, mid + 1, r, ql);
pushup(x);
} #undef ls
#undef rs int merge(int x, int y, int aqzh, int ahzh, int bqzh, int bhzh, int pi) {
if (!x and !y)
return 0;
if (!x) {
pushdown(y);
(sum[y] *= ahzh * (1 - pi + mod) % mod + aqzh * pi % mod) %= mod;
(flag[y] *= ahzh * (1 - pi + mod) % mod + aqzh * pi % mod) %= mod;
return y;
}
if (!y) {
pushdown(x);
(sum[x] *= bhzh * (1 - pi + mod) % mod + bqzh * pi % mod) %= mod;
(flag[x] *= bhzh * (1 - pi + mod) % mod + bqzh * pi % mod) %= mod;
return x;
}
int now = ++tot;
flag[now] = 1;
pushdown(x), pushdown(y);
int a = sum[ch[x][0]], b = sum[ch[y][0]];
ch[now][0] =
merge(ch[x][0], ch[y][0], aqzh, (ahzh + sum[ch[x][1]]) % mod, bqzh, (bhzh + sum[ch[y][1]]) % mod, pi);
ch[now][1] = merge(ch[x][1], ch[y][1], (aqzh + a) % mod, ahzh, (bqzh + b) % mod, bhzh, pi);
pushup(now);
return now;
} void add(int x, int y) {
edge[++cnt].to = y;
edge[cnt].nxt = head[x];
head[x] = cnt;
} int ksm(int a, int b, int ans = 1) {
while (b) {
if (b & 1)
ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
} int getint() {
int X = 0, w = 0;
char ch = getchar();
while (!isdigit(ch)) w |= ch == '-', ch = getchar();
while (isdigit(ch)) X = X * 10 + ch - 48, ch = getchar();
if (w)
return -X;
return X;
} void dfs(int now) {
if (!is[now])
return;
int tot = 0;
for (int i = head[now]; i; i = edge[i].nxt) {
int to = edge[i].to;
tot++;
dfs(to);
}
if (tot == 1) {
for (int i = head[now]; i; i = edge[i].nxt) {
int to = edge[i].to;
rt[now] = rt[to];
}
} else {
tot = 0;
int a, b;
for (int i = head[now]; i; i = edge[i].nxt) {
int to = edge[i].to;
tot == 1 ? b = to : a = to, tot++;
}
rt[now] = merge(rt[a], rt[b], 0, 0, 0, 0, val[now] * inv % mod);
}
} void dfs2(int now, int l, int r) {
if (!now)
return;
pushdown(now);
if (l == r)
return (ans += (lef + 1) * g[l] % mod * sum[now] % mod * sum[now] % mod) %= mod, lef++, void();
int mid = l + r >> 1;
dfs2(ch[now][0], l, mid);
dfs2(ch[now][1], mid + 1, r);
} signed main() {
n = getint();
getint();
inv = ksm(10000, mod - 2);
for (int i = 2; i <= n; i++) {
int x = getint();
add(x, i);
is[x] = 1;
}
for (int i = 1; i <= n; i++) {
val[i] = getint();
if (!is[i])
g[++len] = val[i];
}
std::sort(g + 1, g + 1 + len);
len = std::unique(g + 1, g + 1 + len) - g - 1;
for (int i = 1; i <= n; i++) {
if (!is[i]) {
val[i] = std::lower_bound(g + 1, g + 1 + len, val[i]) - g;
modify(rt[i], 1, len, val[i]);
}
}
dfs(1);
dfs2(rt[1], 1, len);
printf("%lld\n", ans);
return 0;
}

[PKUWC2018] Minimax的更多相关文章

  1. BZOJ5461&colon; &lbrack;PKUWC2018&rsqb;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. BZOJ&period;5461&period;&lbrack;PKUWC2018&rsqb;Minimax&lpar;DP 线段树合并&rpar;

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

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

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

  5. LOJ2537:&lbrack;PKUWC2018&rsqb;Minimax——题解

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

  6. &lbrack;BZOJ5461&rsqb;&lbrack;LOJ&num;2537&lbrack;PKUWC2018&rsqb;Minimax&lpar;概率DP&plus;线段树合并&rpar;

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

  7. 【洛谷5298】&lbrack;PKUWC2018&rsqb; Minimax(树形DP&plus;线段树合并)

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

  8. Luogu P5298 &lbrack;PKUWC2018&rsqb;Minimax

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

  9. &lbrack;LOJ2537&rsqb; &lbrack;PKUWC2018&rsqb; Minimax

    题目链接 LOJ:https://loj.ac/problem/2537 洛谷:https://www.luogu.org/problemnew/show/P5298 Solution 不定期诈尸 好 ...

随机推荐

  1. Linux C 字符串函数 strlen&lpar;&rpar;、strcat&lpar;&rpar;、strncat&lpar;&rpar;、strcmp&lpar;&rpar;、strncmp&lpar;&rpar;、strcpy&lpar;&rpar;、strncpy&lpar;&rpar; 详解

      strlen(返回字符串长度) 表头文件 #include <string.h> 定义函数 size_t strlen(const char *s); 函数说明 strlen()用来计 ...

  2. spring&plus;hibernate 实体类注解问题

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.Ann ...

  3. javascript权威指南笔记--javascript语言核心(五)--getter和setter属性

    getter和setter属性: var p = { x:1.0, y:1.0, get r(){ return Math.sqrt(this.x*this.x + this.y * this.y); ...

  4. HDU3033I love sneakers&excl;&lpar;分组背包&rpar;

    http://acm.hdu.edu.cn/showproblem.php?pid=3033 本题的意思就是说现在有n种牌子的鞋子,每种品牌有一些不同的鞋,每双鞋子都有一个特定的权值,现在要求每种品牌 ...

  5. 铁通、长宽网络支付时&OpenCurlyDoubleQuote;签名失败”问题分析及解决方案  &lbrack;88222001&rsqb;验证签名异常&colon;FAIL&lbrack;20131101100002-142&rsqb;

    原文地址:http://bbs.tenpay.com/forum.php?mod=viewthread&tid=13723&highlight=%CC%FA%CD%A8 如果你的是铁通 ...

  6. Oracle backgroup processes

    PMON: Process Monitor 用自己主动注冊动态监听,处理异常进程. SMON: System Monitor 用于instance recovery. LCKn:仅使用于RAC数据库, ...

  7. 使用SAX解析XML文件

    SAX这是Simple API for XML缩写,它不是由引起W3C拟议标准正式.尽管如此,使用SAX很少几个,点儿全部的XML解析器都会支持它. 与DOM比較而言,SAX是一种轻量型的方法. 我们 ...

  8. javascript重修之书&lpar;一&rpar;&colon;如何判断变量的数据类型

    javascript重修之书(一):如何判断变量的数据类型 一:检测值类型 基本类型:(Undefined.Null.Boolean.Number和String) javascript之所以被称为一门 ...

  9. 20155330 2016-2017-2 《Java程序设计》第六周学习总结

    20155330 2016-2017-2 <Java程序设计>第六周学习总结 教材学习内容总结 学习目标 理解流与IO 理解InputStream/OutPutStream的继承架构 理解 ...

  10. A&period; 【UNR &num;1】争夺圣杯

    题解: 一道比较水的题目 按照最一般的思路离散化后枚举最大值 然后考虑最大值的贡献 会发现需要分类讨论一下 发现对一段k的影响是等差数列 所以可以用线段树维护差分数组