离散化后,容易想到设f[i][j]为i节点权值为j的概率,不妨设j权值在左子树,则有f[i][j]=f[lson][j](pi·f[rson][1~j]+(1-pi)·f[rson][j~m])。

  考虑用线段树合并优化这个dp。记录前缀和,合并某节点时,若某棵线段树在该节点处为空,给另一棵线段树打上乘法标记即可。注意前缀和不要算成合并后的了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
#define P 998244353
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,p[N],a[N],b[N],fa[N],root[N],t,ans,cnt;
struct data{int to,nxt;
}edge[N];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
struct data2{int l,r,x,lazy;
}tree[N<<];
void ins(int &k,int l,int r,int x)
{
if (!k) k=++cnt;tree[k].x=;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(tree[k].l,l,mid,x);
else ins(tree[k].r,mid+,r,x);
}
void update(int k,int x)
{
if (!k) return;
tree[k].x=1ll*tree[k].x*x%P;
if (tree[k].lazy) tree[k].lazy=1ll*tree[k].lazy*x%P;
else tree[k].lazy=x;
}
void down(int k){update(tree[k].l,tree[k].lazy),update(tree[k].r,tree[k].lazy),tree[k].lazy=;}
int query(int k,int l,int r,int x)
{
if (!k) return ;
if (l==r) return tree[k].x;
if (tree[k].lazy) down(k);
int mid=l+r>>;
if (x<=mid) return query(tree[k].l,l,mid,x);
else return query(tree[k].r,mid+,r,x);
}
int merge(int x,int y,int l,int r,int s0,int s1,int p)
{
if (tree[x].lazy) down(x);
if (tree[y].lazy) down(y);
if (!x||!y)
{
if (!x) x=y,swap(s0,s1);
update(x,(1ll*p*s1+1ll*(P+-p)*(P+-s1))%P);
return x;
}
if (l<r)
{
int mid=l+r>>;
tree[x].r=merge(tree[x].r,tree[y].r,mid+,r,(s0+tree[tree[x].l].x)%P,(s1+tree[tree[y].l].x)%P,p);
tree[x].l=merge(tree[x].l,tree[y].l,l,mid,s0,s1,p),
tree[x].x=(tree[tree[x].l].x+tree[tree[x].r].x)%P;
}
return x;
}
void dfs(int k)
{
int s=;
for (int i=p[k];i;i=edge[i].nxt)
dfs(edge[i].to),s++;
if (s==) ins(root[k],,m,a[k]);
else if (s==) root[k]=root[edge[p[k]].to];
else root[k]=merge(root[edge[p[k]].to],root[edge[edge[p[k]].nxt].to],,m,,,a[k]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5461.in","r",stdin);
freopen("bzoj5461.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++)
{
int x=read();
fa[i]=x,addedge(x,i);
}
for (int i=;i<=n;i++)
{
a[i]=read();
if (p[i]) a[i]=1ll*a[i]*%P;
else b[++m]=a[i];
}
sort(b+,b+m+);
for (int i=;i<=n;i++) if (!p[i]) a[i]=lower_bound(b+,b+m+,a[i])-b;
dfs();
for (int i=;i<=m;i++)
{
int x=query(root[],,m,i);
ans=(ans+1ll*i*b[i]%P*x%P*x)%P;
}
cout<<ans;
return ;
}

BZOJ5461 PKUWC2018Minimax(概率期望+线段树合并+动态规划)的更多相关文章

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

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

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

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

  3. Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...

  4. 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)

    [BZOJ5469][FJOI2018]领导集团问题(动态规划,线段树合并) 题面 BZOJ 洛谷 题解 题目就是让你在树上找一个最大的点集,使得两个点如果存在祖先关系,那么就要满足祖先的权值要小于等 ...

  5. loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】

    题目链接 loj2537 题解 观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率 先离散化一下权值 显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\) ...

  6. LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)

    题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(x\) 没有子结点,那么它的权值会在输入 ...

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

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

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

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

  9. bzoj 4631: 踩气球 线段树合并

    4631: 踩气球 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 265  Solved: 136[Submit][Status][Discuss] ...

随机推荐

  1. SNAT和DNAT

    1.SNAT iptables防火墙 Centos6.6 64位 iptables 内网:eth0 172.16.4.1 外网:eth 112.112.112.112/24 当有用户访问公网时,修改用 ...

  2. 微信web开发的上传图片js接口

    $('.chooseImage').click(function(){ wx.chooseImage({ count: pic_num, // 默认9,大于9也是显示9 sizeType: ['com ...

  3. bat 传递超过10个参数(bat参数遍历)

    批处理文件中可引用的参数为%0~%9, %0是指批处理文件的本身,也可以说是一个外部命令:%1~%9是批处理参数,也称形参:而替换形参的实参若超过了批处理文件中所规定数值(9个)且想在批处理文件中应用 ...

  4. ASP.NET Core MVC中的IActionFilter.OnActionExecuting方法,可以获取Controller的Action方法参数值

    用过ASP.NET Core MVC中IActionFilter拦截器的开发人员,都知道这是一个非常强大的MVC拦截器.最近才发现IActionFilter的OnActionExecuting方法,甚 ...

  5. 利尔达推出工控解决方式 串口转以太网模块LSD1ES-W5500_S2E0

    利尔达最近推出工控解决方式,串口转以太网模块LSD1ES-W5500_S2E0,模块基于WIZnet-W5500. 同一时候,这也是利尔达科技集团成为WIZnet代理商后,自行推出的第一款基于WIZn ...

  6. Docker搭建Mysql容器

    转载自:http://blog.csdn.net/Mungo/article/details/78521832?locationNum=9&fps=1 本文介绍如何使用docker迅速搭建My ...

  7. bitmap过大无法显示图片的问题 - z

    public Bitmap ratio(Bitmap image, float pixelW, float pixelH) {Bitmap bitmap = null;try {ByteArrayOu ...

  8. 【MEF】构建一个WPF版的ERP系统

    原文:[MEF]构建一个WPF版的ERP系统 引言 MEF是微软的一个扩展性框架,遵循某种约定将各个部件组合起来.而ERP系统的一大特点是模块化,它们两者的相性很好,用MEF构建一个ERP系统是相当合 ...

  9. python 字符串的split()函数详解

    split翻译为分裂.  split()就是将一个字符串分裂成多个字符串组成的列表. split()当不带参数时以空格进行分割,当代参数时,以该参数进行分割. //---当不带参数时 example: ...

  10. 双面间谍(spy)

    双面间谍 链接 分析: 戳这 代码: #include<cstdio> #include<algorithm> #include<cstdio> #include& ...