BZOJ5461: [PKUWC2018]Minimax
BZOJ5461: [PKUWC2018]Minimax
https://lydsy.com/JudgeOnline/problem.php?id=5461
分析:
- 写出\(dp\)式子:$ f[x][i] = sum f[ls][i]\times p\times sum1[rs]j + f[ls][i]\times (1-p)\times sum2[rs]j$
- 这玩意能用线段树合并优化。
- 具体地,我们考虑线段树上维护答案,那么对于合并过程中\(x,y\)两课子树,如果出现某一棵为空的情况,对于另一棵需要乘的值是相同的,此时打标记即可。
- 然后分析\(ls[x],ls[y],rs[x],rs[y]\)互相的贡献即可。
代码:
//f[x][i] = sum f[ls][i]*p*sum1[rs][j](i>j) + f[ls][i]*(1-p)*sum2[rs][j](i<j)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define N 300050
#define mod 998244353
typedef long long ll;
int n,ch[N][2],a[N],cnt,V[N],koishi,root[N];
ll sum[N*20],tag[N*20],ans;
int ls[N*20],rs[N*20];
ll qp(ll x,ll y) {
ll re=1;
for(;y;y>>=1,x=x*x%mod) if(y&1) re=re*x%mod; return re;
}
const ll inv10000=qp(10000,mod-2);
inline void pushup(int p) {sum[p]=(sum[ls[p]]+sum[rs[p]])%mod;}
inline void giv(int p,ll d) {
tag[p]=tag[p]*d%mod; sum[p]=sum[p]*d%mod;
}
inline void pushdown(int p) {
if(tag[p]!=1) {
if(ls[p]) giv(ls[p],tag[p]);
if(rs[p]) giv(rs[p],tag[p]);
tag[p]=1;
}
}
void update(int l,int r,int x,int &p) {
p=++koishi; tag[p]=sum[p]=1;
if(l==r) return ;
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,ls[p]);
else update(mid+1,r,x,rs[p]);
}
int merge(int x,int y,ll gy,ll gx,ll pw) {
// if(!x&&!y) return 0;
if(!x) {giv(y,gy); return y;}
if(!y) {giv(x,gx); return x;}
pushdown(x),pushdown(y);
ll rsx=sum[rs[x]],rsy=sum[rs[y]],lsx=sum[ls[x]],lsy=sum[ls[y]];
ls[x]=merge(ls[x],ls[y],(gy+(1-pw)*rsx)%mod,(gx+(1-pw)*rsy)%mod,pw);
rs[x]=merge(rs[x],rs[y],(gy+pw*lsx)%mod,(gx+pw*lsy)%mod,pw);
pushup(x);
return x;
}
void dfs(int x) {
if(!ch[x][0]&&!ch[x][1]) {
update(1,cnt,a[x],root[x]);
}else if(!ch[x][1]) {
dfs(ch[x][0]);
root[x]=root[ch[x][0]];
}else {
dfs(ch[x][0]), dfs(ch[x][1]);
root[x]=merge(root[ch[x][0]],root[ch[x][1]],0ll,0ll,a[x]*inv10000%mod);
}
}
void solve(int l,int r,int p) {
if(l==r) {
ans=(ans+ll(l)*V[l]%mod*sum[p]%mod*sum[p])%mod;
return ;
}
pushdown(p);
int mid=(l+r)>>1;
if(ls[p]) solve(l,mid,ls[p]);
if(rs[p]) solve(mid+1,r,rs[p]);
}
int main() {
scanf("%d",&n);
int i,x;
for(i=1;i<=n;i++) {
scanf("%d",&x);
if(i==1) continue;
if(!ch[x][0]) ch[x][0]=i;
else ch[x][1]=i;
}
for(i=1;i<=n;i++) {
scanf("%d",&a[i]);
if(!ch[i][0]&&!ch[i][1]) {
V[++cnt]=a[i];
}
}
sort(V+1,V+cnt+1);
for(i=1;i<=n;i++) {
if(!ch[i][0]&&!ch[i][1]) {
a[i]=lower_bound(V+1,V+cnt+1,a[i])-V;
}
}
dfs(1);
solve(1,cnt,root[1]);
printf("%lld\n",(ans+mod)%mod);
}
BZOJ5461: [PKUWC2018]Minimax的更多相关文章
- [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)
还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...
- 题解-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_ ...
- LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并
传送门 题意:自己去看 首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的. 所以我们只需要考虑每一个值的取到的概率. 很容易设计出一个$DP$:设$f_{i,j}$为在第$ ...
- LOJ2537:[PKUWC2018]Minimax——题解
https://loj.ac/problem/2537 参考了本题在网上能找到的为数不多的题解. 以及我眼睛瞎没看到需要离散化,还有不开longlong见祖宗. ——————————————————— ...
- 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)
点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...
- Luogu P5298 [PKUWC2018]Minimax
好劲的题目啊,根本没往线段树合并方面去想啊 首先每种权值都有可能出现,因此我们先排个序然后一个一个求概率 由于此时数的值域变成\([1,m]\)(离散以后),我们可以设一个DP:\(f_{x,i}\) ...
- [LOJ2537] [PKUWC2018] Minimax
题目链接 LOJ:https://loj.ac/problem/2537 洛谷:https://www.luogu.org/problemnew/show/P5298 Solution 不定期诈尸 好 ...
随机推荐
- 2016/05/17 thinkphp3.2.2 分页的使用:①在Home下设置Publics文件夹或在thinkPHP下library的vender 把page.class.php 考贝进入 ②通过new 实例化方式调用 $page=new \Home\Publics\Page($total,3);
注意分页的方法有两种:一种是thinkphp3.2 自带的 另一种是之前新闻页用过的 显示效果稍有差别 显示效果: 细节问题: ①搜索页面 要加session判断 和 分页 ②修改 ...
- 体验DNN演示平台《A Neural Network Playground》(一)
0 本次博客内容简介 本次博客标(一),是因为我自知有些地方还是不理解.本篇博客仅暂时记录第一次玩 A Neural Network Playground的体验,如果后面有了进一步体会,会更新新的内容 ...
- Virtualbox报错------> VirtualBox虚拟机下鼠标不正常的解决方法
在Virtualbox虚拟机下,突然发现鼠标使用不正常.出现2个鼠标,一个是Ubuntu主机下面的鼠标,一个是Window7下的鼠标,但是Win7下的鼠标不可以看得到,但是点击鼠标左右键可以看到有反应 ...
- PHPUnit学习记录
今天是2017-1-17号,昨晚收到邮件,被view code之后,基本全部需要重构,其实我写得php代码里面完全是东拼西凑的代码,自己都不知道什么意思,今天被要求学习PHPUnit了 ------- ...
- ABAP动态生成经典应用之Dynamic SQL Excute 程序
[转自http://blog.csdn.net/mysingle/article/details/678598]开发说明:在SAP的系统维护过程中,有时我们需要修改一些Table中的数据,可是很多Ta ...
- js判断undefined类型,undefined,null, 的区别详细解析
js判断undefined类型 今天使用showModalDialog打开页面,返回值时.当打开的页面点击关闭按钮或直接点浏览器上的关闭则返回值是undefined所以自作聪明判断 var reVal ...
- Python基础(3)_可变对象与不可变对象、列表、元祖和字典
可变对象与不可变对象 实例被创建后,身份和类型是不可变的, 如果值是不可以被修改的,则是不可变对象 如果值是可以被修改的,则是可变对象 #在id不动,type也不动,value被修改了,则称为可变 # ...
- IAR 条件断点
条件断点是IDE的一个重要功能,在IAR调试时候,经常跟踪一个数据,但是对较大的buffer,用普通的断点或live watch都不好跟踪. 比如某个buffer里一个数,我们知道他在第几个,但是却从 ...
- 20145229吴姗珊 《Java程序设计》第7周学习总结
20145229吴姗珊 <Java程序设计>第7周学习总结 教材学习内容总结 第13章时间与日期 即使标注为GMT(格林威治时间),实际上谈到的的是UTC(Unix时间)时间. 秒的单位定 ...
- 《机器学习实战》学习笔记第十一章 —— Apriori算法
主要内容: 一.关联分析 二.Apriori原理 三.使用Apriori算法生成频繁项集 四.从频繁项集中生成关联规则 一.关联分析 1.关联分析是一种在大规模数据集中寻找有趣关系的任务.这些关系可以 ...