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项加起来就好了. 这个感 ...
随机推荐
- 一个只有十行的精简MVVM框架(上篇)
本文来自网易云社区. 前言 MVVM模式相信做前端的人都不陌生,去网上搜MVVM,会出现一大堆关于MVVM模式的博文,但是这些博文大多都只是用图片和文字来进行抽象的概念讲解,对于刚接触MVVM模式的新 ...
- jenkins配置git+maven+Publish over SSH
一.配置git 1.新建项目,源码管理选择git 2.Repository URL输入git目录 3.Credentials中选择新增凭据,凭据类型选择SSH,usename输入git,passphr ...
- wpf基础使用_修改窗体图标
废话不多说,直接开始修改图标步骤: 当然直接使用绝对路径添加图标也是可以的,这种方式不可取,一旦图标移动位置或被删除,就会导致找不到图标文件报错,这里我们介绍的是另一个方式,使用资源文件的方式添加 1 ...
- [CodeForce721C]Journey
题目描述 Recently Irina arrived to one of the most famous cities of Berland - the Berlatov city. There a ...
- CodeForces - 776C(前缀和+思维)
链接:CodeForces - 776C 题意:给出数组 a[n] ,问有多少个区间和等于 k^x(x >= 0). 题解:求前缀和,标记每个和的个数.对每一个数都遍历到1e5,记录到答案. # ...
- 【json提取器】- 提取数据的方法
json 提取器的使用 方法 json 提取器 提取的结果 我用调试取样器进行查看
- post接口_form表单上传
上传文件的本质是浏览器读取本地文件的内容,以二进制数据方式传输到服务端,服务端新建一个文件,将获取到的数据复制到文件中 LR中上传操作可以通过web_submit_data函数实现,支持录制要点:we ...
- selenium常用操作方法
Webdriver中比较常用的操作元素的方法: clear() 清除输入框的默认内容 send_keys("xxx") 在一个输入框里输入xx内容 ——如果输入中文,则需要在脚本开 ...
- mysql 主从配置笔记
1.master配置 server-id=1 log-bin=mysql-bin binlog-do-db=testdata binlog-ignore-db=mysql 2.master增加用户 g ...
- HDU 1007 Quoit Design(计算几何の最近点对)
Problem Description Have you ever played quoit in a playground? Quoit is a game in which flat rings ...