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天每一天走的距离记录在一起,成 ...
随机推荐
- vue和webpack打包 项目相对路径修改
一般vue使用webpack打包是整个工程的根目录,但是很多情况下都是把vue打包后的文件在某子目录下. 修改: 1,打开index.js assetsPublicPath:'/' 改为: asset ...
- SQLite 知识摘要 --- 事务
在许多时候,我们在使用大数据的时候会发现,尽管sqlite数据库的执行效率已经很快了,但是还是满足不了我们的需求,这时候我们会很容易考虑到使用并发的方式去访问sqlite数据库,但是sqlite数据独 ...
- Java并发编程(三)Thread类的使用
一.线程的状态 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time wait ...
- Kotlin入门(11)江湖绝技之特殊函数
上一篇文章介绍了Kotlin对函数的输入参数所做的增强之处,其实函数这块Kotlin还有好些重大改进,集中体现在几类特殊函数,比如泛型函数.内联函数.扩展函数.尾递归函数.高阶函数等等,因此本篇文章就 ...
- [20171206]rman与truncate.txt
[20171206]rman与truncate.txt --//昨天下班在回家的路上,突然想起以前遇到的问题,就是truncate表后,rman做备份时会备份多少truncate表的信息,--//当时 ...
- zabbix-Get value from agent failed: cannot connect to [[127.0.0.1]:10050]: [111] Connection refused
监控zabbix服务端这台服务器,然后显示Get value from agent failed: cannot connect to [[127.0.0.1]:10050]: [111] Conne ...
- 【PAT】B1044 火星数字(20 分)
/* 火星文有两位,第二位为0不输出 */ #include<stdio.h> #include<algorithm> #include<string.h> #in ...
- 个人技术博客——linux服务器配置以及flask框架
本次的软件工程实践,我负责我们组后台服务的搭建,我选用了bandwagon的服务器,安装的是Debian GNU/Linux,全程在root用户下操作,后端服务是用python的flask框架,数据库 ...
- CSS Hack的一些知识
测试环境:Windows7 主要测试:IE6.IE7.IE8.Fire Fox3.5.6 次要测试:Chrome4.0.Opera10.10.Safari4.04.360浏览器3.1 为了能够让多个H ...
- 拓普微小尺寸TFT液晶屏-高性价比
智能模块(Smart LCD)是专为工业显示应用而设计的TFT液晶显示模块. 模块自带主控IC.Flash存储器.实时嵌入式操作系统,客户主机可把要存储的数据(如背景图.图标等)存储到屏的flash中 ...