LOJ2537:[PKUWC2018]Minimax——题解
参考了本题在网上能找到的为数不多的题解。
以及我眼睛瞎没看到需要离散化,还有不开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——题解的更多相关文章
- LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并
传送门 题意:自己去看 首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的. 所以我们只需要考虑每一个值的取到的概率. 很容易设计出一个$DP$:设$f_{i,j}$为在第$ ...
- [LOJ2537] [PKUWC2018] Minimax
题目链接 LOJ:https://loj.ac/problem/2537 洛谷:https://www.luogu.org/problemnew/show/P5298 Solution 不定期诈尸 好 ...
- [PKUWC2018]Minimax 题解
根据题意,若一个点有子节点,则给出权值:否则可以从子节点转移得来. 若没有子节点,则直接给出权值: 若只有一个子节点,则概率情况与该子节点完全相同: 若有两个子节点,则需要从两个子节点中进行转移. 如 ...
- 【题解】PKUWC2018简要题解
[题解]PKUWC2018简要题解 Minimax 定义结点x的权值为: 1.若x没有子结点,那么它的权值会在输入里给出,保证这类点中每个结点的权值互不相同. 2.若x有子结点,那么它的权值有p的概率 ...
- BZOJ5461: [PKUWC2018]Minimax
BZOJ5461: [PKUWC2018]Minimax https://lydsy.com/JudgeOnline/problem.php?id=5461 分析: 写出\(dp\)式子:$ f[x] ...
- 题解-PKUWC2018 Minimax
Problem loj2537 Solution pkuwc2018最水的一题,要死要活调了一个多小时(1h59min) 我写这题不是因为它有多好,而是为了保持pkuwc2018的队形,与这题类似的有 ...
- [PKUWC2018] Minimax
Description 给定一棵 \(n\) 个节点的树,每个节点最多有两个子节点. 如果 \(x\) 是叶子,则给定 \(x\) 的权值:否则,它的权值有 \(p_x\) 的概率是它子节点中权值的较 ...
- BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)
BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...
- [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)
还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...
随机推荐
- Vs2015 遇到 CL:fatal error c1510 cannot load language clui.dll
网上说什么点击修复VS,修改VS的,经验证都不好使,直接下载这个库,放在system32/64下面皆可以了
- Lua学习笔记(1): HelloWorld和数据类型
Lua是一个轻量级的脚本语言,由c语言编写,容易嵌入到应用中,深受游戏开发者的青睐 环境安装 选用SciTE作为lua的IDE 可以在github找到这个开源的软件 SciTE下载链接 安装好之后打开 ...
- [SHELL]退出脚本
一,退出状态码 1,范围:0~255 2,查看退出状态码:必须在命令执行之后立即执行 ,显示的是脚本最后一条命令的退出状态码 echo $? 若f返回值为0,则表示正常 有异常为正值 二,exit 脚 ...
- 利用maven进行项目管理
下面为maven项目管理的一个结构 首先pom是路径文件,我们在编译或是运行程序时调用到jdk或一些自己写的jar包时会需要指明物理路径,这里的pom是一样的道理,同时在maven的管理下多出来了一些 ...
- opencv-学习笔记(5)形态学转变
opencv-学习笔记(4)形态学转变 本章讲了几种形态学操作 腐蚀erode 膨胀dilate 开运算MORPH_OPEN 闭运算MORPH_CLOSE 形态学梯度MORPH_GRADIENT 礼帽 ...
- selenium元素定位不到之iframe---基于python
我们在使用selenium的18中定位方式的时候,有时会遇到定位不上的问题,今天我们就来说说导致定位不上的其中一个原因---iframe 问题描述:通过firebug查询到相应元素的id或name等, ...
- 常用算法Java实现之直接插入排序
直接插入排序是将未排序的数据插入至已排好序序列的合适位置. 具体流程如下: 1.首先比较数组的前两个数据,并排序: 2.比较第三个元素与前两个排好序的数据,并将第三个元素放入适当的位置: 3.比较第四 ...
- 团队选题报告(i know)
一.团队成员及分工 团队名称:I know 团队成员: 陈家权:选题报告word撰写 赖晓连:ppt制作,原型设计 雷晶:ppt制作,原型设计 林巧娜:原型设计,博客随笔撰写 庄加鑫:选题报告word ...
- Uncaught Error: Syntax error, unrecognized expression: |117的js错误
117指的是js代码在浏览器运行时的出错的行号 var a="117|117" 前面的错误是由于有特殊符号“|”,用$("txtId"+a).val();去取 ...
- DDB与DIB
DB与DIB的区别是什么?觉得书上介绍的有点抽象.不容易理解.他们两者之间的区别的“物理意义” [“现实意义”]——姑且这么叫吧,呵呵!被这个问题困扰了很久,所以今天决定好好查资料总结一下,把它彻底搞 ...