LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并
题意:自己去看
首先可以知道,每一个点都有几率被选到,所以$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、线段树合并的更多相关文章
- [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)
还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...
- 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)
点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...
- LOJ2537. 「PKUWC2018」Minimax【概率DP+线段树合并】
LINK 思路 首先暴力\(n^2\)是很好想的,就是把当前节点概率按照权值大小做前缀和和后缀和然后对于每一个值直接在另一个子树里面算出贡献和就可以了,注意乘上选最大的概率是小于当前权值的部分,选最小 ...
- loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】
题目链接 loj2537 题解 观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率 先离散化一下权值 显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\) ...
- 【pkuwc2018】 【loj2537】 Minmax DP+线段树合并
今年年初的时候参加了PKUWC,结果当时这一题想了快$2h$都没有想出来.... 哇我太菜啦.... 昨天突然去搜了下哪里有题,发现$loj$上有于是就去做了下. 结果第一题我5分钟就把所有细节都想好 ...
- BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)
BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...
- [PKUWC2018]Minimax [dp,线段树合并]
好妙的一个题- 我们设 \(f_{i,j}\) 为 \(i\) 节点出现 \(j\) 的概率 设 \(l = ch[i][0] , r = ch[i][1]\) 即左儿子右儿子 设 \(m\) 为叶子 ...
- P6847-[CEOI2019]Magic Tree【dp,线段树合并】
正题 题目链接:https://www.luogu.com.cn/problem/P6847 题目大意 \(n\)个点的一棵树上,每个时刻可以割掉一些边,一些节点上有果实表示如果在\(d_i\)时刻这 ...
- POJ 3162 Walking Race 树形DP+线段树
给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...
随机推荐
- 根据需要扩展java中的ThreadPoolExecutor
经常被重写的三个方法 ThreadPoolExecutor是可扩展的,通过查看源码可以发现,它提供了几个可以在子类化中改写的方法:beforeExecute,afterExecute,terminat ...
- Angular基础(六) DI
一.依赖注入 a) 如果模块A需要依赖模块B,通常的做法是在A中导入B,import{B} from ‘B’,但有一些场合需要解除这种直接依赖,比如单元测试时需要mock一个B对象.还有时要创建B ...
- tinypng upload一键压缩上传工具,告别人肉
地址 项目地址:tinypng-upload 有兴趣的可以玩一玩,因为平时经常会用到图片压缩,上传,如果你也觉得很繁琐的话,这个将会解决你的痛点. 关于 tinypng-upload 这是一个基于 e ...
- recovery 根据@/cache/recovery/block.map描述从data分区升级
随着android版本的更新,系统固件的大小也越来越大,升级包也越来越大,cache分区已经不够存储update.zip了,所以应用把update.zip下载到data分区,默认情况下data分区是可 ...
- 为什么 APM 能提升 IT 团队工作质量?
“有必要吗?”这是很多 IT 专业人员在尝试向团队内部推荐应用程序性能管理价值时所面临的问题.APM(应用程序性能管理)能为公司节约成本,提高内部工作效率,并真实了解用户对公司的系统和产品是否满意.除 ...
- WPF:验证登录后关闭登录窗口,显示主窗口的解决方法
http://www.27ba.com/post/145.html WPF:验证登录后关闭登录窗口,显示主窗口的解决方法 最近想做一个基于Socket的通讯工具,想模仿QQ那样,需要先登录,登录成功后 ...
- JS获取当前星期几的简易写法
var str = "今天是星期" + "日一二三四五六".charAt(new Date().getDay()); mark在此,方便日后复制 原文https ...
- .net 调用R语言的函数(计算统计值pvalue 对应excel :ttest)
Pvalue 计算 项目设计pvalue计算,但是由于.net 没有类似的公式或者函数,最终决定使用.net 调用R语言 采用.net 调用r语言的公用函数 需要安装 r语言环境 https://mi ...
- 【PAT】B1085 PAT单位排行(25 分)(c++实现)
终于做的有点眉目了,今天学习了一点stl的皮毛,解题瞬间变容易了 下边开始分析本题 这道题如果用纯c解决实在太麻烦,试了半天两个超时,果断放弃,还是用map方便: 我的方法与柳神的方法是有区别的,我只 ...
- Frameworks(不定时更新)
iOS8.4 Frameworks 更新时间:2015年8月17日 Accelerate iOS4.0引入了Accelerate框架,该框架的接口可用于执行数学.大数字以及DSP运算.和开发者个人编写 ...