Luogu P5298 PKUWC2018 Minimax 题解 [ 紫 ] [ 树形 dp ] [ 线段树合并 ] [ 概率 dp ]

news/2025/2/10 22:08:20/文章来源:https://www.cnblogs.com/zhr0102/p/18708845

Minimax:线段树合并优化 dp 好题。

树形 dp

因为要求出每一个值的出现概率,首先我们可以想到一个很暴力的 dp 式子。

定义 \(dp_{i,j}\) 表示在节点 \(i\) 时,权值 \(j\) 的出现概率,设 \(l\) 表示左儿子,\(r\) 表示右儿子,则有如下转移:

  • \(j\) 在左儿子中时,\(dp_{i,j}\gets dp_{l,j}\times(p_i\times\sum_{k=1}^{j-1}dp_{r,k}+(1-p_i)\times\sum_{k=j+1}^{V}dp_{r,k})\),理解的话就是对父亲节点选大的还是选小的进行分讨。
  • \(j\) 在右儿子中时,\(dp_{i,j}\gets dp_{r,j}\times(p_i\times\sum_{k=1}^{j-1}dp_{l,k}+(1-p_i)\times\sum_{k=j+1}^Vdp_{l,k})\)

直接转移即可,时间复杂度 \(O(nV)\)

线段树合并优化

显然原来的时间复杂度会炸掉,但是我们发现每个节点最开始时最多只有一个 dp 位置是有值的,所以我们考虑用这种均摊复杂度的线段树合并来优化这个 dp。

因为 dp 转移的时候需要用到前缀和后缀和,所以我们进行 merge 的时候记录节点 \(x,y\) 的前缀和 \(px,py\) 与后缀和 \(sx,sy\) 以及父亲节点的概率 \(p\)

梳理一下 merge 的流程:

  • 进入节点 \(x,y\)
  • 如果 \(x,y\) 其中之一是空树,则说明直接更新 dp 值即可。
    • \(x\) 是空树,对应着上述 \(j\) 在右儿子中的转移方式,则我们对 \(y\) 的整颗子树内的 dp 值全部乘上 \((p\times\sum_{k=1}^{j-1}dp_{l,k}+(1-p)\times\sum_{k=j+1}^Vdp_{l,k})=(p\times px+(1-p)\times sx)\) 即可。这个可以用懒标记实现区间乘。
    • \(y\) 是空树,对应着上述 \(j\) 在左儿子中的转移方式,则我们对 \(x\) 的整颗子树内的 dp 值全部乘上 \((p\times\sum_{k=1}^{j-1}dp_{r,k}+(1-p)\times\sum_{k=j+1}^Vdp_{r,k})=(p\times py+(1-p)\times sy)\) 即可。这个可以用懒标记实现区间乘。
  • 否则就说明要递归合并,递归左右儿子的时候记得更新 \(sx,sy,px,py\) 的值。
  • 最后将左右儿子的 dp 值加起来就是这个区间的 dp 值。

时间复杂度 \(O(n\log n)\)

代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
#define lc(x) (tr[x].ls)
#define rc(x) (tr[x].rs)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
const int N=300005;
const ll mod=998244353;
int n,fa[N],m=0,b[N],son[N][2],cd[N],p[N],ans[N];
ll qpow(ll a,ll b)
{ll res=1;while(b){if(b&1)res=(res*a)%mod;b>>=1;a=(a*a)%mod;}return res;
}
int getrk(int x)
{return (lower_bound(b+1,b+m+1,x)-b);
}
struct Node{int ls,rs;ll dp,tag=1;
};
struct Segtree{Node tr[20*N];int root[N],tot=0;void pushup(int p){tr[p].dp=(tr[lc(p)].dp+tr[rc(p)].dp)%mod;}void pushdown(int p){if(tr[p].tag!=1){tr[lc(p)].tag=(tr[lc(p)].tag*tr[p].tag)%mod;tr[rc(p)].tag=(tr[rc(p)].tag*tr[p].tag)%mod;tr[lc(p)].dp=(tr[lc(p)].dp*tr[p].tag)%mod;tr[rc(p)].dp=(tr[rc(p)].dp*tr[p].tag)%mod;}tr[p].tag=1;}void modify(int p,int v){tr[p].dp=(tr[p].dp*1ll*v)%mod;tr[p].tag=(tr[p].tag*1ll*v)%mod;}void update(int &u,int ln,int rn,int x,ll k){if(u==0)u=++tot;if(ln==rn){tr[u].dp+=k;return;}int mid=(ln+rn)>>1;if(x<=mid)update(lc(u),ln,mid,x,k);else update(rc(u),mid+1,rn,x,k);pushup(u);}int merge(int x,int y,int px,int py,int sx,int sy,int p){if(x==0&&y==0)return 0;if(x==0){modify(y,(1ll*p*px%mod+1ll*((1-p)%mod+mod)%mod*sx)%mod);return y;}if(y==0){modify(x,(1ll*p*py%mod+1ll*((1-p)%mod+mod)%mod*sy)%mod);return x;}pushdown(x);pushdown(y);int lx=tr[lc(x)].dp,rx=tr[rc(x)].dp,ly=tr[lc(y)].dp,ry=tr[rc(y)].dp;tr[x].ls=merge(lc(x),lc(y),px,py,(sx+rx)%mod,(sy+ry)%mod,p);tr[x].rs=merge(rc(x),rc(y),(px+lx)%mod,(py+ly)%mod,sx,sy,p);pushup(x);return x;}void query(int u,int ln,int rn){if(ln==rn){ans[ln]=tr[u].dp;return;}int mid=(ln+rn)>>1;pushdown(u);query(lc(u),ln,mid);query(rc(u),mid+1,rn);}
}tr1;
void dfs1(int u)
{if(son[u][0]==0){tr1.update(tr1.root[u],1,m,getrk(p[u]),1);return;}if(son[u][1]==0){dfs1(son[u][0]);tr1.root[u]=tr1.root[son[u][0]];return;}dfs1(son[u][0]);dfs1(son[u][1]);tr1.root[u]=tr1.merge(tr1.root[son[u][0]],tr1.root[son[u][1]],0,0,0,0,p[u]);
}
int main()
{//freopen("sample.in","r",stdin);//freopen("sample.out","w",stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;for(int i=1;i<=n;i++)cin>>fa[i];for(int i=1;i<=n;i++){son[fa[i]][cd[fa[i]]]=i;cd[fa[i]]++;}for(int i=1;i<=n;i++){cin>>p[i];if(cd[i])p[i]=p[i]*1ll*qpow(10000,mod-2)%mod;else b[++m]=p[i];}sort(b+1,b+m+1);m=unique(b+1,b+m+1)-b-1;dfs1(1);tr1.query(tr1.root[1],1,m);ll res=0;for(int i=1;i<=m;i++)res=(res+1ll*i*b[i]%mod*ans[i]%mod*ans[i]%mod)%mod;cout<<res;return 0;
}

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

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

相关文章

ACM寒假集训第四期

ACM寒假集训第四期 有理数取余 思路 bx=a mod m x=((a mod m) * ( b^(-1) ) mod m)) mod m; 问题就转化为如何求解 b 的逆元 b x = 1 mod m ,b对m的逆元,当 gcd(b,m)=1 时才存在。存在 bx+my=1 通过辗转相除法可以得到b,m的最大公约数然后根据最后得到的一系列等式合并为 bx+m…

昆明理工大学2025年硕士研究生调剂汇总表(2月10日更新)

这是今年昆明理工大学调剂信息,目前只更新了部分学院的部分专业,后续会持续更新。 【腾讯文档】昆明理工大学2025年硕士研究生调剂汇总表 https://docs.qq.com/sheet/DZERIbnpPb3JjeHFO

推荐一款人人可用的开源 BI 工具,更符合国人使用习惯的数据可视化分析工具,数据大屏开发神器!

前言 今天大姚给大家推荐一款人人可用的开源、免费的 BI 工具,更符合国人使用习惯的数据可视化分析工具,数据大屏开发神器,Tableau、帆软的开源替代:DataEase。工具介绍 DataEase是一个开源的数据可视化分析工具,可以帮助用户快速分析数据并洞察业务趋势,从而实现业务的改…

清华大学推出的 DeepSeek 从入门到精通(104页)免费教程!

前言 最近 DeepSeek 的出现让 AI 在国内掀起了一股浪潮,各大媒体、平台都在讨论和推广 DeepSeek,帮助各行各样使用 AI 不再有困难。今天大姚给大家分享一个由清华大学推出的、免费的:DeepSeek从入门到精通实用教程,该教材有着足足的104页能够快速的帮助大家了解和使用DeepS…

卞俊良

卞俊良 你猜 你猜我猜不猜

P1314 [NOIP 2011 提高组] 聪明的质监员(前缀和)

这道题最核心就是二分W,然后对于每一个W都构建一个前缀和数组,但要注意ans不能开太小,我开INT_MAX都不行,其次就是二分左右端点的变化,如果s-y>0说明满足要求的点多了,这时候我们要提高标准,就是让W增大,及让beign=W+1,反之让end=W-1;如果s=y,此时ans=0;这时候我…

读读源码-ArrayList究竟是怎么实现增强for循环的?

以我的认知来说,java中的ArrayList实现List,List又是继承Collection,往后就不太清楚了。 今天看源码的时候发现Collection继承了Iterable,Iterable接口的作用是允许对象称为for-each loop语句的目标。 因此如果想了解ArrayList如何实现循环,我们必须先从Iterable看起 1.集…

“此电脑”不是“我的电脑”怎么办

在以前,我们可以按住win+E就可以打开到有盘符的界面(直接看见C盘,D盘,E盘……),现在win11没有这个效果了,我还得再在左边的选项里寻找“此电脑”再进入我想要的“我的电脑”界面,真麻烦!无缘无故多了几个点击步骤,效率真低! 今天,我想改变这个效果!自已自足!。。…

香港海底光缆-转载2020

转自:http://live.xiaohongshu.com.sdwan.ltd/index.php?m=home&c=View&a=index&aid=132香港作为全球重要数据传输驿站之一,其网络传输能力自然不可小瞧。根据香港政府通讯事务管理局办公室给出的资料,截至2019年1月,香港有十一个海缆系统,即亚非欧1号光缆系…

miniconda安装和配置

第一步,下载和安装访问Download Anaconda Distribution | Anaconda,跳过注册"Skip registration",进入下载界面往下拉,选择miniconda的下载。安装时候注意勾选PATH路径的配置选项。第二步,安装完成后通过Anaconda Prompt打开命令行,看到提示符前面有(base)字…

智能化物资安全管理:AI视频监控在大型商场的技术方案介绍(part3)

项目背景:商场在运营中面临商品失窃的风险,需要通过技术手段实时预防偷窃行为,保护物资安全。 一、具体需求: 1、姿势与行为异常识别:检测顾客的异常行为,例如夹带物品、将商品从货架放入包中等动作。 2、异常行为检测:监控顾客长时间逗留、异常交互(如反复拿取同一物品…