https://loj.ac/problem/2537

参考了本题在网上能找到的为数不多的题解。

以及我眼睛瞎没看到需要离散化,还有不开longlong见祖宗。

————————————————————————————

思考一下不难发现,我们的操作相当于对两个数集进行合并,并且重新更新每个数被取到的期望。

权值线段树可以帮我们实现这个功能(当然是要动态开点了)。

然后就思考线段树的合并操作了,orz可我不会啊。

设我们期望让左儿子的数字u成为其父亲的权值,其父亲选最大值的概率为k,u在右儿子数集中比它小的数被选中的期望设为w。

则概率为pu*((1-w)*(1-k)+w*k)=pu*(1-w-k+2*w*k)。

当然右儿子同理。

当然统计w显然不能暴力统计,我们权值线段树维护当前区间所有数被选中的期望和,从左到右扫所有可能的最大区间,这个区间满足有一个儿子的数集并不包含这个区间内的任意一个数。

这样这个区间的期望和就能被缩成了“一个数的期望”,此时的w也很容易被统计出来(就相当于这个区间以前的所有数的期望和,每次扫完一个区间累加即可O(1)求出),那么这个时候就被转换成了区间修改问题。

#include<cmath>
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=3e5+;
const int p=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
int qpow(int k,int n){
int res=;
while(n){
if(n&)res=(ll)res*k%p;
k=(ll)k*k%p;n>>=;
}
return res;
}
struct tree{
int l,r;
ll p,lazy;
}tr[N*];
int fa[N],son[N],ch[N][],rt[N],pool,n,m,b[N],q[N];
inline void LSH(){
sort(b+,b+m+);
m=unique(b+,b+m+)-b-;
for(int i=;i<=n;i++)
if(!son[i])
q[i]=lower_bound(b+,b+m+,q[i])-b;
}
void insert(int &x,int l,int r,int k){
tr[x=++pool].p=;tr[x].lazy=;
if(l==r)return;
int mid=(l+r)>>;
if(k<=mid)insert(tr[x].l,l,mid,k);
else insert(tr[x].r,mid+,r,k);
}
inline void push(int x){
if(tr[x].lazy<=)return;
(tr[tr[x].l].lazy*=tr[x].lazy)%=p;
(tr[tr[x].r].lazy*=tr[x].lazy)%=p;
(tr[tr[x].l].p*=tr[x].lazy)%=p;
(tr[tr[x].r].p*=tr[x].lazy)%=p;
tr[x].lazy=;
}
int maxl,maxr;
int merge(int nl,int nr,int l,int r,int k){
if(!nl&&!nr)return ;
if(!nl){
(maxr+=tr[nr].p)%=p;
(tr[nr].p*=((ll)*maxl%p*k%p-k-maxl+)%p+p)%=p;
(tr[nr].lazy*=((ll)*maxl%p*k%p-k-maxl+)%p+p)%=p;
return nr;
}
if(!nr){
(maxl+=tr[nl].p)%=p;
(tr[nl].p*=((ll)*maxr%p*k%p-k-maxr+)%p+p)%=p;
(tr[nl].lazy*=((ll)*maxr%p*k%p-k-maxr+)%p+p)%=p;
return nl;
}
push(nl);push(nr);
int mid=(l+r)>>;
tr[nl].l=merge(tr[nl].l,tr[nr].l,l,mid,k);
tr[nl].r=merge(tr[nl].r,tr[nr].r,mid+,r,k);
tr[nl].p=(tr[tr[nl].l].p+tr[tr[nl].r].p)%p;
return nl;
}
void dfs(int u){
if(!son[u]){
insert(rt[u],,m,q[u]);return;
}
if(son[u]==){
dfs(ch[u][]);
rt[u]=rt[ch[u][]];
}else{
dfs(ch[u][]);dfs(ch[u][]);
maxl=maxr=;
rt[u]=merge(rt[ch[u][]],rt[ch[u][]],,m,q[u]);
}
}
int cnt;
int query(int x,int l,int r){
if(!tr[x].p)return ;
if(l==r){
cnt++;
return (ll)cnt*b[l]%p*tr[x].p%p*tr[x].p%p;
}
push(x);
int mid=(l+r)>>;
return (query(tr[x].l,l,mid)+query(tr[x].r,mid+,r))%p;
}
int main(){
n=read();
for(int i=;i<=n;i++){
fa[i]=read();
ch[fa[i]][son[fa[i]]++]=i;
}
int inv=qpow(,p-);
for(int i=;i<=n;i++){
q[i]=read();
if(son[i])q[i]=(ll)q[i]*inv%p;
else b[++m]=q[i];
}
LSH();
dfs();
printf("%d\n",query(rt[],,m));
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

LOJ2537:[PKUWC2018]Minimax——题解的更多相关文章

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

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

  2. [LOJ2537] [PKUWC2018] Minimax

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

  3. [PKUWC2018]Minimax 题解

    根据题意,若一个点有子节点,则给出权值:否则可以从子节点转移得来. 若没有子节点,则直接给出权值: 若只有一个子节点,则概率情况与该子节点完全相同: 若有两个子节点,则需要从两个子节点中进行转移. 如 ...

  4. 【题解】PKUWC2018简要题解

    [题解]PKUWC2018简要题解 Minimax 定义结点x的权值为: 1.若x没有子结点,那么它的权值会在输入里给出,保证这类点中每个结点的权值互不相同. 2.若x有子结点,那么它的权值有p的概率 ...

  5. BZOJ5461: [PKUWC2018]Minimax

    BZOJ5461: [PKUWC2018]Minimax https://lydsy.com/JudgeOnline/problem.php?id=5461 分析: 写出\(dp\)式子:$ f[x] ...

  6. 题解-PKUWC2018 Minimax

    Problem loj2537 Solution pkuwc2018最水的一题,要死要活调了一个多小时(1h59min) 我写这题不是因为它有多好,而是为了保持pkuwc2018的队形,与这题类似的有 ...

  7. [PKUWC2018] Minimax

    Description 给定一棵 \(n\) 个节点的树,每个节点最多有两个子节点. 如果 \(x\) 是叶子,则给定 \(x\) 的权值:否则,它的权值有 \(p_x\) 的概率是它子节点中权值的较 ...

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

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

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

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

随机推荐

  1. 网易七鱼 Android 高性能日志写入方案

    本文来自网易云社区 作者:网易七鱼 Android 开发团队 前言 网易七鱼作为一款企业级智能客服系统,对于系统稳定性要求很高,不过难保用户在使用中不会出现问题,而 Android SDK 安装在用户 ...

  2. windows安装logstash-input-jdbc并使用其导入MMSQL数据

    1.安装logstash 2.修改logstash 文件夹下Gemfile文件 将source改为:https://gems.ruby-china.org 3.进入bin目录 执行logstash-p ...

  3. hdu1847Good Luck in CET-4 Everybody!(sg函数)

    Good Luck in CET-4 Everybody! Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  4. Selenium(Python) ddt读取MySQL数据驱动

    import unittestfrom time import sleep from ddt import ddt, datafrom pymysql import connectfrom selen ...

  5. 利用爬虫、SMTP和树莓派3B发送邮件&续集&(爬取墨迹天气预报信息)

    -----------------------------------------------学无止境----------------------------------------------- 前 ...

  6. 【zabbix 监控】第二章 安装测试被监控主机

    客户端安装测试 一.准备两台被监控主机,分别做如下操作: web129:192.168.19.129 web130:192.168.19.130 [root@web129 ~]#yum -y inst ...

  7. Linux系统查看系统版本命令

    以下操作在centos系统上实现,有些方式可能只适用centos/redhat版本系统 uname -a |uname -r查看内核版本信息 [root@node1 ~]# uname -a Linu ...

  8. Red and Black(DFS深搜实现)

    Description There is a rectangular room, covered with square tiles. Each tile is colored either red ...

  9. [离散化]人潮最多的時段( Interval Partitioning Problem )

    範例:人潮最多的時段( Interval Partitioning Problem ) 一群訪客參加宴會,我們詢問到每一位訪客的進場時刻與出場時刻,請問宴會現場擠進最多人的時段. 換個角度想,想像會場 ...

  10. Java中的线程状态转换和线程控制常用方法

    Java 中的线程状态转换: [注]:不是 start 之后就立刻开始执行, 只是就绪了(CPU 可能正在运行其他的线程). [注]:只有被 CPU 调度之后,线程才开始执行, 当 CPU 分配给你的 ...