BZOJ5461 PKUWC2018Minimax(概率期望+线段树合并+动态规划)
离散化后,容易想到设f[i][j]为i节点权值为j的概率,不妨设j权值在左子树,则有f[i][j]=f[lson][j](pi·f[rson][1~j]+(1-pi)·f[rson][j~m])。
考虑用线段树合并优化这个dp。记录前缀和,合并某节点时,若某棵线段树在该节点处为空,给另一棵线段树打上乘法标记即可。注意前缀和不要算成合并后的了。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 300010
#define P 998244353
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,p[N],a[N],b[N],fa[N],root[N],t,ans,cnt;
struct data{int to,nxt;
}edge[N];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
struct data2{int l,r,x,lazy;
}tree[N<<];
void ins(int &k,int l,int r,int x)
{
if (!k) k=++cnt;tree[k].x=;
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(tree[k].l,l,mid,x);
else ins(tree[k].r,mid+,r,x);
}
void update(int k,int x)
{
if (!k) return;
tree[k].x=1ll*tree[k].x*x%P;
if (tree[k].lazy) tree[k].lazy=1ll*tree[k].lazy*x%P;
else tree[k].lazy=x;
}
void down(int k){update(tree[k].l,tree[k].lazy),update(tree[k].r,tree[k].lazy),tree[k].lazy=;}
int query(int k,int l,int r,int x)
{
if (!k) return ;
if (l==r) return tree[k].x;
if (tree[k].lazy) down(k);
int mid=l+r>>;
if (x<=mid) return query(tree[k].l,l,mid,x);
else return query(tree[k].r,mid+,r,x);
}
int merge(int x,int y,int l,int r,int s0,int s1,int p)
{
if (tree[x].lazy) down(x);
if (tree[y].lazy) down(y);
if (!x||!y)
{
if (!x) x=y,swap(s0,s1);
update(x,(1ll*p*s1+1ll*(P+-p)*(P+-s1))%P);
return x;
}
if (l<r)
{
int mid=l+r>>;
tree[x].r=merge(tree[x].r,tree[y].r,mid+,r,(s0+tree[tree[x].l].x)%P,(s1+tree[tree[y].l].x)%P,p);
tree[x].l=merge(tree[x].l,tree[y].l,l,mid,s0,s1,p),
tree[x].x=(tree[tree[x].l].x+tree[tree[x].r].x)%P;
}
return x;
}
void dfs(int k)
{
int s=;
for (int i=p[k];i;i=edge[i].nxt)
dfs(edge[i].to),s++;
if (s==) ins(root[k],,m,a[k]);
else if (s==) root[k]=root[edge[p[k]].to];
else root[k]=merge(root[edge[p[k]].to],root[edge[edge[p[k]].nxt].to],,m,,,a[k]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5461.in","r",stdin);
freopen("bzoj5461.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++)
{
int x=read();
fa[i]=x,addedge(x,i);
}
for (int i=;i<=n;i++)
{
a[i]=read();
if (p[i]) a[i]=1ll*a[i]*%P;
else b[++m]=a[i];
}
sort(b+,b+m+);
for (int i=;i<=n;i++) if (!p[i]) a[i]=lower_bound(b+,b+m+,a[i])-b;
dfs();
for (int i=;i<=m;i++)
{
int x=query(root[],,m,i);
ans=(ans+1ll*i*b[i]%P*x%P*x)%P;
}
cout<<ans;
return ;
}
BZOJ5461 PKUWC2018Minimax(概率期望+线段树合并+动态规划)的更多相关文章
- [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)
还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...
- LOJ2537. 「PKUWC2018」Minimax【概率DP+线段树合并】
LINK 思路 首先暴力\(n^2\)是很好想的,就是把当前节点概率按照权值大小做前缀和和后缀和然后对于每一个值直接在另一个子树里面算出贡献和就可以了,注意乘上选最大的概率是小于当前权值的部分,选最小 ...
- Codeforces 700E. Cool Slogans 字符串,SAM,线段树合并,动态规划
原文链接https://www.cnblogs.com/zhouzhendong/p/CF700E.html 题解 首先建个SAM. 一个结论:对于parent树上任意一个点x,以及它所代表的子树内任 ...
- 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)
[BZOJ5469][FJOI2018]领导集团问题(动态规划,线段树合并) 题面 BZOJ 洛谷 题解 题目就是让你在树上找一个最大的点集,使得两个点如果存在祖先关系,那么就要满足祖先的权值要小于等 ...
- loj2537 「PKUWC2018」Minimax 【概率 + 线段树合并】
题目链接 loj2537 题解 观察题目的式子似乎没有什么意义,我们考虑计算出每一种权值的概率 先离散化一下权值 显然可以设一个\(dp\),设\(f[i][j]\)表示\(i\)节点权值为\(j\) ...
- LOJ #2537. 「PKUWC 2018」Minimax (线段树合并 优化dp)
题意 小 \(C\) 有一棵 \(n\) 个结点的有根树,根是 \(1\) 号结点,且每个结点最多有两个子结点. 定义结点 \(x\) 的权值为: 1.若 \(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}$为在第$ ...
- bzoj 4631: 踩气球 线段树合并
4631: 踩气球 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 265 Solved: 136[Submit][Status][Discuss] ...
随机推荐
- 配置openfire环境
Openfire 的安装和配置 1. 下载最新的openfire安装文件 官方下载站点:http://www.igniterealtime.org/downloads/index.jsp#openfi ...
- phpstorm开发环境搭建流程
1.下载phpstorm 2.网上找注册码 phpstorm 8 license key Learn Programming===== LICENSE BEGIN =====63758-1204201 ...
- 快速在Ubuntu安装PHP网站
快速安装使用的是tasksel,tasksel是Debian / Ubuntu的工具,安装多个相关软件包作为一个协调的“任务”到你的系统.这个lamp-server^跟taskel这个程序有关.下面是 ...
- Docker:一个装应用的容器
一:简介:你是否经历过“我本地运行没问题啊!““哪个哥们有写死循环了““完了,服务器撑不住了“等等问题,docker就是这么帮你解决问题的工具,它可以帮你把web应用自动化打包和发布,在服务型环境下进 ...
- js开关插件使用
一.简介 本篇文章介绍一个比较好使用的js开关插件Switchery,该插件的样式是ios7的滑动按钮插件,并且将很多功能加入到配置项,简单.灵活,支持的绝大部分浏览器(Chrome, Firefox ...
- 20155217《网络对抗》Exp03 免杀原理与实践
20155217<网络对抗>Exp03 免杀原理与实践 实践内容 正确使用msf编码器,msfvenom生成如jar之类的其他文件,veil-evasion,自己利用shellcode编程 ...
- Vue 项目集合
饿了么安全应急响应中心 饿了么招聘 饿了么前端 · GitHub 稀土掘金 异乡好居 明星垂搜 广州建管 基于Vue.js的数据统计系统(一) 基于Vue.js的数据统计系统(二) 基于Vue.js的 ...
- 【php增删改查实例】第八节 - 部门管理模块(编写PHP程序)
首先,在同级目录新建一个query.php文件: 接着,去刷新页面,打开F12,NetWork,看看当前的请求能不能走到对应的php文件? 这就说明datagrid确实能够访问到query.php 只 ...
- grunt-inline:一个资源内嵌插件
一.插件简介 将引用的外部资源,如js.css.img等,内嵌到引用它们的文件里去. 二.使用场景 在项目中,出于某些原因,有的时候我们需要将一些资源,比如js脚本内嵌到页面中去.比如我们的html页 ...
- tensorflow 曲线拟合
tensorflow 曲线拟合 Python代码: import numpy as np import tensorflow as tf import matplotlib.pyplot as plt ...