今年年初的时候参加了PKUWC,结果当时这一题想了快$2h$都没有想出来....

哇我太菜啦....

昨天突然去搜了下哪里有题,发现$loj$上有于是就去做了下。

结果第一题我5分钟就把所有细节都想好了啊5555....

场上$60pts$消失...


显然,我们可以用$f[i][j]$表示节点$i$值为第$j$大的值的概率。

我们不难列出$dp$式子,$f[i][j]=f[s1][j] \times (s[s2][j-1]\times p+(s[s2][m]-s[s2][j])\times (1-p))$。

其中$s[i][j]=\sum_{k=0}{j} f[i][k]$。$s1$表示可以取到第j大的数的儿子,$s2$表示不能取到第$j$大的数的儿子。

显然,直接转移是$O(n^2)$的(我场上就写了这个)。

考虑如何进行优化。

题目中有一些特别优美的条件,比如说所有的数不会重复,树最多只有两个分叉。

如果某个树只有一个分叉的话,显然直接复制根即可,时间复杂度为$O(1)$。

考虑用线段树优化,考虑如何合并$s1$和$s2$这两棵树。

假设我们当前要合并的区间为$[l,r]$,且$x,y$分别为线段树中$s1,s2$用来表示区间$[l,r]$的节点。

对于该区间,我们用$xs1$来表示$s[s2][l-1]$,用$xs2$来表示$(s[s2][m]-s[s2][r])$。对于$s2$同理(暂且用$ys1,ys2$表示)。

递归的时候,若往线段树的左儿子递归,那么$xs2$就要加上$x$的右儿子的概率和,$ys2$同理。若线段树往右儿子递归,也同理。

然后当递归到$x$或$y$中有一个不存在时,直接用$xs1/2$,$ys1/2$更新即可。

(若$l==r$,则更新方式与上述$dp$式子相同,若$l≠r$,打个标记就行了)

考虑到线段树合并的时间复杂度为$O(n log n)$。所以这种方法是可以通过的。

完结撒花~~

 #include<bits/stdc++.h>
#define L long long
#define MOD 998244353
#define M 300005
using namespace std; L pow_mod(L x,L k){
L ans=;
while(k){
if(k&) ans=ans*x%MOD;
x=x*x%MOD; k>>=;
}
return ans;
} int lc[M*]={},rc[M*]={},root[M]={},use=;
L p[M*]={},tag[M*]={},gailv[M]={};
int l[M]={},r[M]={}; void pushdown(int x){
if(tag[x]!=){
if(lc[x]!=) tag[lc[x]]=tag[lc[x]]*tag[x]%MOD,p[lc[x]]=p[lc[x]]*tag[x]%MOD;
if(rc[x]!=) tag[rc[x]]=tag[rc[x]]*tag[x]%MOD,p[rc[x]]=p[rc[x]]*tag[x]%MOD;
tag[x]=;
}
}
void pushup(int x){p[x]=(p[lc[x]]+p[rc[x]])%MOD;} void updata(int &x,int l,int r,int k){
if(!x) {x=++use; p[x]=tag[x]=;}
if(l==r){p[x]=tag[x]=; return;}
int mid=(l+r)>>;
if(k<=mid) updata(lc[x],l,mid,k);
if(mid<k) updata(rc[x],mid+,r,k);
pushup(x);
} L nowp;
int solve(int x,int y,L xs1,L xs2,L ys1,L ys2){
if(x==&&y==) return ;
if(y==){
L upd=(xs1*nowp+xs2*(-nowp+MOD))%MOD;
tag[x]=upd*tag[x]%MOD;
p[x]=upd*p[x]%MOD;
return x;
}
if(x==){
L upd=(ys1*nowp+ys2*(-nowp+MOD))%MOD;
tag[y]=upd*tag[y]%MOD;
p[y]=upd*p[y]%MOD;
return y;
}
pushdown(x); pushdown(y);
L p1=p[lc[y]],p2=p[lc[x]];
lc[x]=solve(lc[x],lc[y],xs1,(xs2+p[rc[y]])%MOD,ys1,(ys2+p[rc[x]])%MOD);
rc[x]=solve(rc[x],rc[y],(xs1+p1)%MOD,xs2,(ys1+p2)%MOD,ys2);
pushup(x);
return x;
} void dfs(int x){
if(l[x]) dfs(l[x]);
if(r[x]) dfs(r[x]);
if(!l[x]) return;
if(!r[x]) {root[x]=root[l[x]]; return;}
nowp=gailv[x];
root[x]=solve(root[l[x]],root[r[x]],,,,);
}
L w[M]={},hh[M]={}; int m=; L ans=;
void getans(int x,L l,L r){
if(l==r){
ans=(ans+l*hh[l]%MOD*p[x]%MOD*p[x])%MOD;
return;
}
pushdown(x);
L mid=(l+r)>>;
getans(lc[x],l,mid);
getans(rc[x],mid+,r);
} int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n; scanf("%d",&n);
for(int i=;i<=n;i++){
int x; scanf("%d",&x);
if(!l[x]) l[x]=i;
else r[x]=i;
}
L inv10000=pow_mod(,MOD-);
for(int i=;i<=n;i++){
L x; scanf("%lld",&x);
if(l[i]) gailv[i]=x*inv10000%MOD;
else w[i]=x,hh[++m]=x;
}
sort(hh+,hh+m+);
for(int i=;i<=n;i++) if(w[i]){
int x; x=lower_bound(hh+,hh+m+,w[i])-hh;
updata(root[i],,m,x);
}
dfs();
getans(root[],,m);
printf("%lld\n",ans);
}

【pkuwc2018】 【loj2537】 Minmax DP+线段树合并的更多相关文章

  1. [BZOJ5461][LOJ#2537[PKUWC2018]Minimax(概率DP+线段树合并)

    还是没有弄清楚线段树合并的时间复杂度是怎么保证的,就当是$O(m\log n)$吧. 这题有一个显然的DP,dp[i][j]表示节点i的值为j的概率,转移时维护前缀后缀和,将4项加起来就好了. 这个感 ...

  2. LOJ2537. 「PKUWC2018」Minimax【概率DP+线段树合并】

    LINK 思路 首先暴力\(n^2\)是很好想的,就是把当前节点概率按照权值大小做前缀和和后缀和然后对于每一个值直接在另一个子树里面算出贡献和就可以了,注意乘上选最大的概率是小于当前权值的部分,选最小 ...

  3. BZOJ.5461.[PKUWC2018]Minimax(DP 线段树合并)

    BZOJ LOJ 令\(f[i][j]\)表示以\(i\)为根的子树,权值\(j\)作为根节点的概率. 设\(i\)的两棵子树分别为\(x,y\),记\(p_a\)表示\(f[x][a]\),\(p_ ...

  4. 【洛谷5298】[PKUWC2018] Minimax(树形DP+线段树合并)

    点此看题面 大致题意: 有一棵树,给出每个叶节点的点权(互不相同),非叶节点\(x\)至多有两个子节点,且其点权有\(p_x\)的概率是子节点点权较大值,有\(1-p_x\)的概率是子节点点权较小值. ...

  5. [PKUWC2018]Minimax [dp,线段树合并]

    好妙的一个题- 我们设 \(f_{i,j}\) 为 \(i\) 节点出现 \(j\) 的概率 设 \(l = ch[i][0] , r = ch[i][1]\) 即左儿子右儿子 设 \(m\) 为叶子 ...

  6. P6847-[CEOI2019]Magic Tree【dp,线段树合并】

    正题 题目链接:https://www.luogu.com.cn/problem/P6847 题目大意 \(n\)个点的一棵树上,每个时刻可以割掉一些边,一些节点上有果实表示如果在\(d_i\)时刻这 ...

  7. 洛谷P4577 [FJOI2018]领导集团问题(dp 线段树合并)

    题意 题目链接 Sol 首先不难想到一个dp,设\(f[i][j]\)表示\(i\)的子树内选择的最小值至少为\(j\)的最大个数 转移的时候维护一个后缀\(mx\)然后直接加 因为后缀max是单调不 ...

  8. BZOJ 5469: [FJOI2018]领导集团问题 dp+线段树合并

    在 dp 问题中,如果发现可以用后缀最大值来进行转移的话可以考虑去查分这个后缀最大值. 这样的话可以用差分的方式来方便地进行维护 ~ #include <bits/stdc++.h> #d ...

  9. LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并

    传送门 题意:自己去看 首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的. 所以我们只需要考虑每一个值的取到的概率. 很容易设计出一个$DP$:设$f_{i,j}$为在第$ ...

随机推荐

  1. 二叉树的遍历——Morris

    在之前的博客中,博主讨论过二叉树的经典遍历算法,包括递归和常规非递归算法,其时间复杂度和空间复杂度均为O(n).Morris算法巧妙地利用了二叉树的线索化思路,将二叉树的遍历算法的空间复杂度降低为O( ...

  2. 20155207 2016-2017-2 《Java程序设计》第九周学习总结

    20155207 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 第16章 整合数据库 16.1 JDBC入门 16.1.1 JDBC简介 数据库本身是个独立 ...

  3. hdu-1209(细节题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1209 注意:1.时钟到12要变为0 2.注意比较角度相同的情况 #include<iostrea ...

  4. Mac pro 安装IntelliJ IDEA 2017版

    1.官网下载这个版本https://www.jetbrains.com 2.点击下载即可 3.下载好后放入本地 4.启动mac终端进行破解 输入命令:sudo vim /private/etc/hos ...

  5. html自适应布局,@media screen,媒体查询

    html自适应布局,@media screen,媒体查询 自适应代码示例: <!doctype html> <html> <head> <meta chars ...

  6. dos常用命令使用说明

    cd 改变当前目录 sys 制作DOS系统盘 copy 拷贝文件 del 删除文件 deltree 删除目录树 dir 列文件名 diskcopy 制磁盘 edit 文本编辑 format 格式化磁盘 ...

  7. SpringMVC 示例实战教程

    一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要的jar包. 2.添加Web.xml配置文件中关于SpringMVC的配置 1 2 3 4 5 6 ...

  8. [ACM_模拟] UVA 12504 Updating a Dictionary [字符串处理 字典增加、减少、改变问题]

      Updating a Dictionary  In this problem, a dictionary is collection of key-value pairs, where keys ...

  9. rtmp官方标准规范详细解析

    标准规范学习: rtmp消息结构,包括几个部分: 时戳:4  byte,单位毫秒.超过最大值后会翻转. 长度:消息负载的长度. 类型ID:Type Id 一部分ID范围用于rtmp的控制信令.还有一部 ...

  10. MVC批量上传文件

    初始图片: 选中图片后 ---------------------------------------------------------------------------------- 前端代码 ...