传送门

题意:自己去看


首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的。

所以我们只需要考虑每一个值的取到的概率。

很容易设计出一个$DP$:设$f_{i,j}$为在第$i$个点取到权值第$j$小的点的概率,转移就是$f_{i,j}=f_{lson,j} \times (\sum \limits _{k<i} f_{rson,k} \times p_x + \sum \limits _{k > i} f_{rson,k} \times (1 - p_x))$($lson$和$rson$之间可以交换),显然是可以前缀和优化的

当然前缀和优化也不够,$O(n^2)$只能过$40pts$。考虑优化。发现在合并的时候$lson$与$rson$之间的元素是互不冲突的,所以可以考虑线段树合并,每一次合并的时候把两边的贡献记录下来,在线段树上打标记即可。

 #include<bits/stdc++.h>
#define ld long double
#define int long long
#define mid ((l + r) >> 1)
#define lch Tree[now].ch[0]
#define rch Tree[now].ch[1]
//This code is written by Itst
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MAXN = , MOD = ;
struct node{
int mark , sum , ch[];
}Tree[MAXN * ];
int pri[MAXN] , root[MAXN] , lsh[MAXN] , ch[MAXN][] , cnt , N , cntNode , ny; inline void pushup(int now){
Tree[now].sum = (Tree[lch].sum + Tree[rch].sum) % MOD;
} inline void pushdown(int now){
if(Tree[now].mark != ){
Tree[lch].sum = Tree[lch].sum * Tree[now].mark % MOD;
Tree[rch].sum = Tree[rch].sum * Tree[now].mark % MOD;
Tree[lch].mark = Tree[lch].mark * Tree[now].mark % MOD;
Tree[rch].mark = Tree[rch].mark * Tree[now].mark % MOD;
Tree[now].mark = ;
}
} void insert(int& now , int l , int r , int tar){
if(!now){
now = ++cntNode;
Tree[now].mark = ;
}
if(l == r){
Tree[now].sum = ;
return;
}
pushdown(now);
if(mid >= tar)
insert(lch , l , mid , tar);
else
insert(rch , mid + , r , tar);
pushup(now);
} int mer(int p , int q , int markp , int markq , int pri){
if(!(p + q))
return ;
if(!p){
Tree[q].mark = Tree[q].mark * markq % MOD;
Tree[q].sum = Tree[q].sum * markq % MOD;
return q;
}
if(!q){
Tree[p].mark = Tree[p].mark * markp % MOD;
Tree[p].sum = Tree[p].sum * markp % MOD;
return p;
}
pushdown(p);
pushdown(q);
int m1 = Tree[Tree[q].ch[]].sum , n1 = Tree[Tree[p].ch[]].sum , m2 = Tree[Tree[q].ch[]].sum , n2 = Tree[Tree[p].ch[]].sum;
Tree[p].ch[] = mer(Tree[p].ch[] , Tree[q].ch[] , (markp + m1 * ( - pri) % MOD * ny) % MOD , (markq + n1 * ( - pri) % MOD * ny) % MOD , pri);
Tree[p].ch[] = mer(Tree[p].ch[] , Tree[q].ch[] , (markp + m2 * pri % MOD * ny) % MOD , (markq + n2 * pri % MOD * ny) % MOD , pri);
pushup(p);
return p;
} int getAns(int now , int l , int r){
if(l == r)
return l * lsh[l] % MOD * Tree[now].sum % MOD * Tree[now].sum % MOD;
else{
pushdown(now);
return (getAns(lch , l , mid) + getAns(rch , mid + , r)) % MOD;
}
} void dfs(int now){
if(!ch[now][])
insert(root[now] , , cnt , pri[now]);
else
if(!ch[now][]){
dfs(ch[now][]);
root[now] = root[ch[now][]];
}
else{
dfs(ch[now][]);
dfs(ch[now][]);
root[now] = mer(root[ch[now][]] , root[ch[now][]] , , , pri[now]);
}
} inline int poww(long long a , int b){
int times = ;
while(b){
if(b & )
times = times * a % MOD;
a = a * a % MOD;
b >>= ;
}
return times;
} signed main(){
#ifndef ONLINE_JUDGE
freopen("2537.in" , "r" , stdin);
//freopen("2537.out" , "w" , stdout);
#endif
N = read();
for(int i = ; i <= N ; ++i){
int a = read();
if(!ch[a][])
ch[a][] = i;
else
ch[a][] = i;
}
ny = poww( , MOD - );
for(int i = ; i <= N ; ++i){
pri[i] = read();
if(!ch[i][])
lsh[++cnt] = pri[i];
}
sort(lsh + , lsh + cnt + );
for(int i = ; i <= N ; ++i)
if(!ch[i][])
pri[i] = lower_bound(lsh + , lsh + cnt + , pri[i]) - lsh;
dfs();
cout << getAns(root[] , , cnt);
return ;
}

LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并的更多相关文章

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

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

  2. 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)

    点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...

  3. LOJ2537. 「PKUWC2018」Minimax【概率DP+线段树合并】

    LINK 思路 首先暴力\(n^2\)是很好想的,就是把当前节点概率按照权值大小做前缀和和后缀和然后对于每一个值直接在另一个子树里面算出贡献和就可以了,注意乘上选最大的概率是小于当前权值的部分,选最小 ...

  4. loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】

    题目链接 loj2537 题解 观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率 先离散化一下权值 显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\) ...

  5. 【pkuwc2018】 【loj2537】 Minmax DP+线段树合并

    今年年初的时候参加了PKUWC,结果当时这一题想了快$2h$都没有想出来.... 哇我太菜啦.... 昨天突然去搜了下哪里有题,发现$loj$上有于是就去做了下. 结果第一题我5分钟就把所有细节都想好 ...

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

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

  7. [PKUWC2018]Minimax [dp,线段树合并]

    好妙的一个题- 我们设 \(f_{i,j}\) 为 \(i\) 节点出现 \(j\) 的概率 设 \(l = ch[i][0] , r = ch[i][1]\) 即左儿子右儿子 设 \(m\) 为叶子 ...

  8. P6847-[CEOI2019]Magic Tree【dp,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/P6847 题目大意 \(n\)个点的一棵树上,每个时刻可以割掉一些边,一些节点上有果实表示如果在\(d_i\)时刻这 ...

  9. POJ 3162 Walking Race 树形DP+线段树

    给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...

随机推荐

  1. 【读书笔记】iOS-优化内存

    imageNamed:方法创建UIImage对象,这些对象不再使用的时候 会放到应用的默认自动回收池中,而不是当前的事件循环的自动回收池中,这样的对象占用的内存只有在应用结束的时候 才会回收.如果用这 ...

  2. 【读书笔记】iOS-深入解剖对等网络

    协议本身是一个运行在UDP之上的定制协议.我所以决定使用一个定制协议很简单.首先,当前这个任务看起来足够简单,因此与尝试改进一个现在协议相比,直接构建一个定制协议更为容易.其次,定制协议可以将开销减少 ...

  3. Linux 磁盘分区方案简析

    Linux 磁盘分区方案简析 by:授客 QQ:1033553122   磁盘分区 任何硬盘在使用前都要进行分区.硬盘的分区有两种类型:主分区和扩展分区.一个硬盘上最多只能有4个主分区,其中一个主分区 ...

  4. 【Java入门提高篇】Day32 Java容器类详解(十四)ArrayDeque详解

    今天来介绍一个不太常见也不太常用的类——ArrayDeque,这是一个很不错的容器类,如果对它还不了解的话,那么就好好看看这篇文章吧. 看完本篇,你将会了解到: 1.ArrayDeque是什么? 2. ...

  5. asp.net学习——Response对象

    (2011-03-29 07:33:03) 转载▼ 标签: 杂谈 分类: asp.net学习 响应的缓冲输出:为了提高服务器的性能,asp.net向浏览器Write的时候默认并不会每Write一次都会 ...

  6. nginx1.14的安装

    编译安装nginx1.14.2 #拷贝指定文件到当前目录下[root@localhost ~]# find /usr/share -iname "*.jpg" -exec cp { ...

  7. Visual Studio 2015的安装与测试单元的配置与使用

    首先感谢吴小勇同学的教程,及其详尽周全.详见http://www.cnblogs.com/xiaoyongwu/p/5289964.html     那么正式开始,事实上在撰写这篇博文的时候,这个图标 ...

  8. POI写Word换行

    本文旨在描述基于变量替换生成Word doc文件的换行方式.Word换行主要有两大类,一类是表格单元格文本的换行,另一类是表格之外的文本的换行.对于表格外的文本我们可以使用“\r”或者“(char)1 ...

  9. C#の----Func,Action,predicate在WPF中的应用

    首先介绍下,winform中可以用this.invoke来实现:wpf中要使用调度器Control.Despite.invoke: (Action)(()=> { })和 new Action ...

  10. Android的面向组件思想

    http://blog.csdn.net/luoxinwu123/article/details/8019547 面向组件思想是在软件规模扩大,复杂度上升的背景下,以面向对象为基础而提出的一种软件设计 ...