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项加起来就好了. 这个感 ...
随机推荐
- Selenium(Python)等待元素出现
1.显式等待 from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdri ...
- Appium(Python)驱动手机淘宝App
请注意操作步骤: 1. 用数据线连接手机, 打开开发者模式, 并赋予相关权限, 并保持不锁屏状态: 2. 启动Appium桌面服务端: 3. 运行程序: 首次运行, Appium会在手机上安装3个Ap ...
- Python函数变量和返回值
Python函数的全局变量和局部变量 1.不同的编程语言,程序可以分为函数和过程两大类,函数具有具体返回值,而过程则不具有具体的返回值,python只具有函数,因为对于它的一般函数,其返回值为所具体返 ...
- 【icon】 图标组件说明
小程序默认了几种类型图标,其组件原型如下: <icon type="[success | success_no_circle | info | warn | waiting | can ...
- lintcode39 恢复旋转排序数组
恢复旋转排序数组 给定一个旋转排序数组,在原地恢复其排序. 您在真实的面试中是否遇到过这个题? Yes 说明 什么是旋转数组? 比如,原始数组为[1,2,3,4], 则其旋转数组可以是[1,2,3 ...
- 贪心算法——Huffman 压缩编码的实现
1. 如何理解 "贪心算法" 假设我们有一个可以容纳 100 Kg 物品的背包,可以装各种物品.我们有以下 5 种豆子,每种豆子的总量和总价值都各不相同.怎样装才能让背包里豆子的总 ...
- POJ 3415 Common Substrings(后缀数组)
Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤i+k-1≤|T|. Given t ...
- H5页面 绝对定位元素被 软键盘弹出时顶起
H5页面 绝对定位元素被 软键盘弹出时顶起 在h5页面开发的过程中,我们可能会遇到下面这个问题,当页面中有输入框的时候,系统自带的软盘会把按钮挤出原来的位置.那么我们该怎么解决呢?下面列出一下的方法: ...
- 简介Kafka Streams
本文从以下几个方面介绍Kafka Streams: 一. Kafka Streams 背景 二. Kafka Streams 架构 三. Kafka Streams 并行模型 四. Kafka Str ...
- [CLR via C#]值类型的装箱和拆箱
我们先来看一个示例代码: namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Array ...