题解-PKUWC2018 Minimax
Problem
Solution
pkuwc2018最水的一题,要死要活调了一个多小时(1h59min)
我写这题不是因为它有多好,而是为了保持pkuwc2018的队形,与这题类似的有一个好玩得多的题
由于答案的形式和期望相去甚远,所以可以肯定这题和期望无关,而且这么复杂的式子我们最好还是把所有可能计算出来啦
可以肯定地说这题是从叶子向根合并,合并时分类讨论下取最大\((p)\)还是最小\((1-p)\),然后维护前后缀概率和即可
再瞟一眼数据,发现线段树合并可以解决,完结
Code
注意由于线段树合并时若一个节点为空则直接返回,但这棵子树需要乘上整体概率,所以还要在裸的线段树合并中加上标记维护
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline void read(int&x){
char c11=getchar();x=0;while(!isdigit(c11))c11=getchar();
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();
}
const int N=301050,M=N*10,p=998244353;
struct Edge{int v,nxt;}a[N];
int ls[M],rs[M],f[M],lz[M];
int head[N],c[N],b[N],rt[N];
int n,_,tot;
template <typename _tp> inline _tp qm(_tp x){return x<0?x+p:x<p?x:x-p;}
void update(int l,int r,int&x,int vl){
if(!x)lz[x=++tot]=1;
if(l==r){f[x]=1;return ;}
int mid(l+r>>1);
if(vl<=mid)update(l,mid,ls[x],vl);
else update(mid+1,r,rs[x],vl);
f[x]=qm(f[ls[x]]+f[rs[x]]);
}
inline void mul(int x,int vl){
f[x]=1ll*f[x]*vl%p;
lz[x]=1ll*lz[x]*vl%p;
}
inline void down(int x){
if(ls[x])mul(ls[x],lz[x]);
if(rs[x])mul(rs[x],lz[x]);
lz[x]=1;
}
int merge(int x,int y,ll p0,ll p1,ll p2){
if(x&&lz[x]!=1)down(x);
if(y&&lz[y]!=1)down(y);
if(!x){mul(y,p0*p1%p+qm(1-p0)*qm(1-p1)%p);return y;}
if(!y){mul(x,p0*p2%p+qm(1-p0)*qm(1-p2)%p);return x;}
rs[x]=merge(rs[x],rs[y],p0,qm(p1+f[ls[x]]),qm(p2+f[ls[y]]));
ls[x]=merge(ls[x],ls[y],p0,p1,p2);
f[x]=qm(f[ls[x]]+f[rs[x]]);
return x;
}
void dfs(int x){
for(int i=head[x];i;i=a[i].nxt){
dfs(a[i].v);
if(!rt[x])rt[x]=rt[a[i].v];
else rt[x]=merge(rt[x],rt[a[i].v],c[x],0ll,0ll);
}
if(!head[x])update(1,n,rt[x],c[x]);
}
int calc(int l,int r,int x){
if(lz[x]!=1)down(x);
if(l==r)return 1ll*l *b[l]%p *f[x]%p *f[x]%p;
int mid(l+r>>1);
return qm(calc(l,mid,ls[x])+calc(mid+1,r,rs[x]));
}
int main(){
read(n);
for(int i=1,x;i<=n;++i){
read(x),a[++_].v=i;
a[_].nxt=head[x],head[x]=_;
}
int tt=0;const ll inv5=796898467;
for(int i=1;i<=n;++i){
read(c[i]);
if(head[i])c[i]=inv5*c[i]%p;
else b[++tt]=c[i];
}
sort(b+1,b+tt+1);
int end=unique(b+1,b+tt+1)-b;
for(int i=1;i<=n;++i)
if(!head[i])c[i]=lower_bound(b+1,b+end,c[i])-b;
n=end-1;dfs(1);
printf("%d\n",calc(1,n,1));
return 0;
}
题解-PKUWC2018 Minimax的更多相关文章
- BZOJ5461: [PKUWC2018]Minimax
BZOJ5461: [PKUWC2018]Minimax https://lydsy.com/JudgeOnline/problem.php?id=5461 分析: 写出\(dp\)式子:$ f[x] ...
- LOJ2537:[PKUWC2018]Minimax——题解
https://loj.ac/problem/2537 参考了本题在网上能找到的为数不多的题解. 以及我眼睛瞎没看到需要离散化,还有不开longlong见祖宗. ——————————————————— ...
- [PKUWC2018]Minimax 题解
根据题意,若一个点有子节点,则给出权值:否则可以从子节点转移得来. 若没有子节点,则直接给出权值: 若只有一个子节点,则概率情况与该子节点完全相同: 若有两个子节点,则需要从两个子节点中进行转移. 如 ...
- 题解-PKUWC2018 随机算法
Problem loj2540 题意简述:给定\(n\)个点的无向图,给定求最大独立集的近似算法:随机排列\(1\cdots n\),按照该排列顺序贪心构造最大独立集(即对每个点能加入独立集就加),求 ...
- [PKUWC2018] Minimax
Description 给定一棵 \(n\) 个节点的树,每个节点最多有两个子节点. 如果 \(x\) 是叶子,则给定 \(x\) 的权值:否则,它的权值有 \(p_x\) 的概率是它子节点中权值的较 ...
- 题解-PKUWC2018 Slay the Spire
Problem loj2538 Solution 在考场上当然要学会写暴力,考虑如果手上已经有了\(a\)张攻击牌和\(b\)张强化牌: 首先强化牌会在攻击牌之前用(废话),其次要将两种牌分别从大往小 ...
- 题解-PKUWC2018 随机游走
Problem loj2542 题意:一棵 \(n\) 个结点的树,从点 \(x\) 出发,每次等概率随机选择一条与所在点相邻的边走过去,询问走完一个集合 \(S\)的期望时间,多组询问 \(n\le ...
- BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)
BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...
- LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并
传送门 题意:自己去看 首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的. 所以我们只需要考虑每一个值的取到的概率. 很容易设计出一个$DP$:设$f_{i,j}$为在第$ ...
随机推荐
- 【SQL】SqlServer中Group By后,字符串合并
参考: 1.SQL查询语句 group by后, 字符串合并 2.sql for xml path用法 #需求: 合并列值 表结构,数据如下: id value ----- ------ aa bb ...
- Sublime Text3中 less 自动编译成 css 的方法
使用sublime text的less2css插件 步骤: 1.安装node.js,这个到官网下载即可 2.安装less,方法:命令行输入: npm install -g less 3.sublime ...
- 13个.Net开源的网络爬虫
请点击此处输入图片描述 1:.Net开源的跨平台爬虫框架 DotnetSpider Star:430 DotnetSpider这是国人开源的一个跨平台.高性能.轻量级的爬虫软件,采用 C# 开发.目前 ...
- 快速学习 javascript
// js 6种数据类型:字符串.数值.布尔值.undefined.null.object // 三种非数字的数字类型:Infinity -Infinity NaN var str = "H ...
- zsh,oh-my-zsh,antigen使用记录
关于 'zsh': 又名 z shell,‘z' 是26个字母中的最后一位,故取意为“终极终端”. 关于 'oh-my-zsh': 是一个针对zsh的模板化的z shell配置脚本,目标是配置一个好用 ...
- js伪数组转数组
方法1: 遍历伪数组,在把值push进一个空数组中 方法2: 使用数组的slice方法,它返回的是数组,使用call或apply指向伪数组 var arr = [].slice.call(argume ...
- 第19月第20天 UITableView:改变 TableHeaderView 的高度 获取目录大小
1.UITableView:改变 TableHeaderView 的高度 CGRect newFrame = headerView.frame; newFrame.size.height = newF ...
- python2 编码与解码
#!coding: utf-8 s = "特斯拉" s_to_unicode = s.decode("utf-8") unicode_to_gbk = s_to ...
- flask处理cookie
一 什么是cookie 什么是cookie?如果单单从数据结构的角度来说,它可以被理解成用来保存数据的一个dictionary,由一组组键值对组成.如果从作用上来说,我们知道Http协议是一种无状态的 ...
- 登录mysql时的一些命令
清屏: cls 只要输入cls然后回车运行命令,可以清屏. 查看版本号: mysql -V 注意:V一定要大写,如果不大写就错了... 登录: mysql -u用户名 -p密码 -P端口号 -h数据库 ...