传送门

题意:自己去看


首先可以知道,每一个点都有几率被选到,所以$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. 从零开始学习html(一) Html介绍

    我是初学者,这个是我学习的过程,当做笔记记录下来,如有错误希望高手指正. 原地址 一.代码初体验,制作我的第一个网页 <!DOCTYPE HTML> <html> <he ...

  2. docker第一章:docker核心概念及centos6下安装

    Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...

  3. 编程实践:使用java访问mySQL数据库

    1.虚拟机安装mySQL 服务器, 宿主机分别使用navicat工具和java代码 访问mySQL,组网图如下: 2. 查看mySQL的服务器状态,如下: 3. 服务器上查看数据库和数据表内容如下: ...

  4. Linux 操作系统主机名变成bogon怎么解决?

    主机名变成bogon怎么解决? by:授客 QQ:1033553122   一:使用hostname命令 [laiyu@localhost ~]$ hostname localhost.localdo ...

  5. Spark内存分配诊断

    1.JVM自带众多内存诊断的工具,例如:JMap,JConsole等,第三方IBM JVM Profile Tools等. 2.日志!在开发.测试.生产环境中最合适的就是日志,特别是Driver产生的 ...

  6. 【redis专题(1)】安装与启动

    简介 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo(redis之父)写的key-value存储系统. Redis提供了一些丰富的数据 ...

  7. [20170828]grep过滤技巧.txt

    [20170828]grep过滤技巧.txt --//经常使用grep过滤显示信息. #  ps -ef |grep oraagentoracle    13416      1  0  2016 ? ...

  8. python第三十六天-----类中的特殊成员方法

    __doc__ 查看尖的描述信息 __module__表示当前操作的对象所在的模块 __class__表示当前操作的对象所属的类 __init__构造方法 通过类创建对象自动执行 __del__析构方 ...

  9. tomcat 7.0 最大连接数和线程设置

    部署项目时需要根据服务器配置调整连接数 <Connector port="8080" protocol="HTTP/1.1"URIEncoding=&qu ...

  10. January 18th, 2018 Week 03rd Thursday

    To strive, to seek, to find, and not to yield. 去奋斗,去寻觅,去探索,但绝不屈服. Strive for our dreams, seek the ve ...